home *** CD-ROM | disk | FTP | other *** search
/ Aminet 51 / Aminet 51 (2002)(GTI - Schatztruhe)[!][Oct 2002].iso / Aminet / dev / c / minigl.lha / MiniGL / src / vertexarray.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-07-03  |  76.9 KB  |  3,419 lines

  1. /*
  2.  * $Id: vertexarray.c,v 1.3 2001/02/05 16:56:03 tfrieden Exp $
  3.  *
  4.  * $Date: 2001/02/05 16:56:03 $
  5.  * $Revision: 1.3 $
  6.  *
  7.  * (C) 1999 by Hyperion
  8.  * All rights reserved
  9.  *
  10.  * This file is part of the MiniGL library project
  11.  * See the file Licence.txt for more details
  12.  *
  13.  */
  14.  
  15. /*
  16. ** glDrawArrays pipeline by Christian 'SuRgEoN' Michael
  17. ** Thanks to Olivier Fabre for bug-hunting
  18. */
  19.  
  20. /*
  21. ** revised 07-04-02:
  22. **
  23. ** In some cases A_DrawTriangles didn't use the correct
  24. ** start position during backface-culling
  25. **
  26. ** Support for GL_EXT_compiled_vertex_array was added.
  27. **
  28. ** When Clip_Volume_Bypass is GL_FALSE, it will wrap
  29. ** to GLDrawElements (at the very beginning of GLDrawArrays,
  30. ** which is ofcourse not an optimal solution.
  31. ** Anyways, the use if glDrawArrays is probably rare in case
  32. ** of compiled arrays, but it should be supported.
  33. ** One possible solution to this is to make the default
  34. ** W3D_VertexPointer point to the W3D_Vertex struct inside
  35. ** the vertexbuffer like for elements, but it would probably
  36. ** lower the general performance of glDrawArrays.
  37. */
  38.  
  39.  
  40. #include "sysinc.h"
  41. #include "vertexarray.h"
  42. #include <stdio.h>
  43. #include <stdlib.h>
  44. #include <string.h>
  45. #include <math.h>
  46.  
  47.  
  48. /*
  49.  
  50. NOTE:
  51.     Transformation and clipping pipeline can be turned on/off with glDisable/glEnable(MGL_ARRAY_TRANSFORMATIONS) before the pointers are set.
  52.  
  53. The MGL_FLATFAN will work regardless of pipeline state.
  54.  
  55. Tricky stuff:
  56.  
  57. Problem 1: We don't want to copy texcoords unless we really have to (clipping) and we don't want to write the w-coords to application-arrays since a texcoordpointer is allowed to have a stride of 2.
  58.  
  59.     Current solution:
  60.     We allocate some memory exclusively for the w-coords
  61.     in order to cope with any texcoordstride.
  62.     The relative w-coord buffer offset is calculated
  63.     whenever texcoordpointer is set.
  64.  
  65. Problem 2: Clipping events are expensive because texcoords and colors currently need to be converted and copied to the vertexbuffer.
  66.  
  67.     Solution: ?? Currently, a sort of guardband is used
  68.              in order to avoid clipping in most cases.
  69.  
  70.  
  71. TODO:
  72.  
  73. - Implement remaining GL primitives.
  74. - Implement MGL_UBYTE_ARGB color-format (Voodoo3 native)
  75. - Write pointer-wrapper for glInterleavedArrays and proper
  76.   optimized conversion-routines for clipping.
  77. - Implement multitexturing (virtual TMU for now).
  78.  
  79. */
  80.  
  81.  
  82.  
  83. //NYI:
  84.  
  85. void A_DrawPoints        (GLcontext context, const int first, const int count);
  86. void A_DrawLines         (GLcontext context, const int first, const int count);
  87. void A_DrawLineStrip     (GLcontext context, const int first, const int count);
  88. void A_DrawLineLoop      (GLcontext context, const int first, const int count);
  89.  
  90. void A_DrawQuads         (GLcontext context, const int first, const int count);
  91. void A_DrawQuadStrip      (GLcontext context, const int first, const int count);
  92.  
  93. //implemented:
  94.  
  95. void A_DrawTriFan       (GLcontext context, const int first, const int count);
  96. void A_DrawTriStrip       (GLcontext context, const int first, const int count);
  97. void A_DrawTriangles     (GLcontext context, const int first, const int count);
  98. void A_DrawPolygon       (GLcontext context, const int first, const int count);
  99. void A_DrawFlatFan       (GLcontext context, const int first, const int count);
  100.  
  101.  
  102. extern void TMA_Start(LockTimeHandle *handle);
  103. extern GLboolean TMA_Check(LockTimeHandle *handle);
  104. extern void fog_Set(GLcontext context);
  105. static INLINE void PreDraw(GLcontext context);
  106. static INLINE void PostDraw(GLcontext context);
  107.  
  108.  
  109. static GLboolean Reset_W3D_VertexPointer = GL_TRUE;
  110.  
  111. int A_TransformArray (GLcontext context, const int first, const int size);
  112.  
  113. void A_ToScreenArray(GLcontext context, const int first, const int size);
  114.  
  115.  
  116. extern void m_CombineMatrices(GLcontext context);
  117.  
  118.  
  119. //Culling:
  120.  
  121. GLboolean DecideFrontface(GLcontext context, const MGLVertex *a, const MGLVertex *b, const MGLVertex *c, int sign);
  122.  
  123.  
  124. //Clipping (convert color and texcoords to vertexbuffer)
  125.  
  126. void Convert_F_RGB(GLcontext context, int i);
  127. void Convert_F_RGBA(GLcontext context, int i);
  128. void Convert_UB_RGB(GLcontext context, int i);
  129. void Convert_UB_RGBA(GLcontext context, int i);
  130. void Convert_UB_BGR(GLcontext context, int i);
  131. void Convert_UB_BGRA(GLcontext context, int i);
  132. void Convert_UB_ARGB(GLcontext context, int i);
  133.  
  134. //pointer to color/texcoord conversion routine for clipping events:
  135.  
  136. Convfn Convert = (Convfn)Convert_F_RGBA;
  137.  
  138. extern void AE_ClipPoly(GLcontext context, PolyBuffer *out, int clipstart, ULONG or_codes); 
  139.  
  140.  
  141.  
  142. //stuff for compiled arrays:  added 07-04-2002
  143.  
  144. extern GLboolean Clip_Volume_Bypass;
  145.  
  146. #define MAX_ELEMENTS 16384 //should be enough
  147.  
  148. static UWORD e_wrap[MAX_ELEMENTS]; //should be enough 
  149.  
  150. //called from MGLInit:
  151.  
  152. void Init_ArrayToElements_Warpper(void)
  153. {
  154.     int i;
  155.  
  156.     for (i=0; i<MAX_ELEMENTS; i++)
  157.         e_wrap[i] = i;
  158. }
  159.  
  160. //called at the very beginning of GLDrawArrays in case clipping is needed with compiled arrays:
  161.  
  162. extern void GLDrawElements(GLcontext context, GLenum mode, const GLsizei count, GLenum type, const GLvoid *indices);
  163.  
  164. // end of compiled arrays support
  165.  
  166.  
  167. int A_TransformArray (GLcontext context, const int first, const int size)
  168. {
  169.    int i;
  170.    ULONG and_code, or_code, guard_band;
  171.  
  172.         #define OF_11 0
  173.         #define OF_12 4
  174.         #define OF_13 8
  175.         #define OF_14 12
  176.  
  177.         #define OF_21 1
  178.         #define OF_22 5
  179.         #define OF_23 9
  180.         #define OF_24 13
  181.  
  182.         #define OF_31 2
  183.         #define OF_32 6
  184.         #define OF_33 10
  185.         #define OF_34 14
  186.  
  187.         #define OF_41 3
  188.         #define OF_42 7
  189.         #define OF_43 11
  190.         #define OF_44 15
  191.  
  192.         #define a(x) (context->CombinedMatrix.v[OF_##x])
  193.  
  194.    if(context->ArrayPointer.FixpointTrans == GL_TRUE)
  195.    {
  196.     static int m[16];
  197.     int tx,ty,tz,tw;
  198.     int x,y,z;
  199.       int *vp;
  200.     ULONG local_outcode;
  201.     UBYTE *vpointer;
  202.     MGLVertex *v;
  203.     int stride;
  204.  
  205.       #define CLIP_EPS ((int)((1e-7)*32768.f))
  206.      #define b(x) (m[OF_##x])
  207.  
  208.       if(context->CombinedValid == GL_FALSE)
  209.     {
  210.     const float float2fix = 32768.f;
  211.  
  212.             m_CombineMatrices(context);
  213.  
  214.         b(11)=(int)(a(11)*float2fix);
  215.         b(12)=(int)(a(12)*float2fix);
  216.         b(13)=(int)(a(13)*float2fix);
  217.         b(14)=(int)(a(14)*float2fix);
  218.         b(21)=(int)(a(21)*float2fix);
  219.         b(22)=(int)(a(22)*float2fix);
  220.         b(23)=(int)(a(23)*float2fix);
  221.         b(24)=(int)(a(24)*float2fix);
  222.         b(31)=(int)(a(31)*float2fix);
  223.         b(32)=(int)(a(32)*float2fix);
  224.         b(33)=(int)(a(33)*float2fix);
  225.         b(34)=(int)(a(34)*float2fix);
  226.         b(41)=(int)(a(41)*float2fix);
  227.         b(42)=(int)(a(42)*float2fix);
  228.         b(43)=(int)(a(43)*float2fix);
  229.         b(44)=(int)(a(44)*float2fix);
  230.     }
  231.  
  232.      stride = context->ArrayPointer.vertexstride;
  233.      vpointer = (context->ArrayPointer.verts + first*stride);
  234.  
  235.      and_code = 0xff;
  236.      or_code = 0;
  237.  
  238.      v = &(context->VertexBuffer[first]);
  239.  
  240.      i = size;
  241.      do
  242.      {
  243.  
  244.       vp = (int *)vpointer;
  245.  
  246.       x = vp[0];
  247.       y = vp[1];
  248.       z = vp[2];
  249.  
  250. //pipelined transformations
  251.  
  252.        tx  = x*b(11);
  253.        ty  = x*b(21);
  254.        tz  = x*b(31);
  255.        tw  = x*b(41);
  256.  
  257.     tx += y*b(12);
  258.     ty += y*b(22);
  259.     tz += y*b(32);
  260.     tw += y*b(42);
  261.  
  262.     tx += z*b(13);
  263.     ty += z*b(23);
  264.     tz += z*b(33);
  265.     tw += z*b(43);
  266.  
  267.     tx += b(14);
  268.     ty += b(24);
  269.     tz += b(34);
  270.     tw += b(44);
  271.  
  272.     local_outcode = 0;
  273.  
  274.         if (tw < CLIP_EPS )
  275.       {
  276.                 local_outcode |= MGL_CLIP_NEGW;
  277.       }        
  278.         if (-tw > tx)
  279.         {
  280.                 local_outcode |= MGL_CLIP_LEFT;
  281.         }
  282.         else if (tx > tw)
  283.         {
  284.                 local_outcode |= MGL_CLIP_RIGHT;
  285.         }
  286.  
  287.         if (-tw > ty)
  288.         {
  289.                 local_outcode |= MGL_CLIP_BOTTOM;
  290.         }
  291.         else if (ty > tw)
  292.         {
  293.                 local_outcode |= MGL_CLIP_TOP;
  294.         }
  295.         
  296.         if (-tw > tz)
  297.         {
  298.                 local_outcode |= MGL_CLIP_BACK;
  299.         }
  300.         else if (tz > tw)
  301.         {
  302.                 local_outcode |= MGL_CLIP_FRONT;
  303.         }
  304.  
  305.     v->bx = (float)tx;    
  306.     v->by = (float)ty;
  307.     v->bz = (float)tz;    
  308.     v->bw = (float)tw;    
  309.  
  310.       v->outcode = local_outcode;
  311.       and_code &= local_outcode;
  312.       or_code  |= local_outcode;
  313.  
  314.      v++; vpointer += stride;
  315.  
  316.      } while (--i);
  317.  
  318.     #undef b
  319.     #undef CLIP_EPS    
  320.    }
  321.    else
  322.    {
  323.       float a11,a12,a13,a14;
  324.       float a21,a22,a23,a24;
  325.       float a31,a32,a33,a34;
  326.       float a41,a42,a43,a44;
  327.       float *vp;
  328.       float cw;
  329.     float x,y,z;
  330.     ULONG local_outcode;
  331.     UBYTE *vpointer;
  332.     MGLVertex *v;
  333.     int stride;
  334.  
  335.       #define CLIP_EPS (1e-7)
  336.  
  337.      if(context->CombinedValid == GL_FALSE)
  338.             m_CombineMatrices(context);
  339.  
  340.      a11=a(11); a12=a(12); a13=a(13); a14=a(14);
  341.      a21=a(21); a22=a(22); a23=a(23); a24=a(24);
  342.      a31=a(31); a32=a(32); a33=a(33); a34=a(34);
  343.      a41=a(41); a42=a(42); a43=a(43); a44=a(44);
  344.  
  345.      stride = context->ArrayPointer.vertexstride;
  346.      vpointer = (context->ArrayPointer.verts + first*stride);
  347.  
  348.      v = &(context->VertexBuffer[first]);
  349.  
  350.      i = size;
  351.  
  352.      do
  353.      {
  354.         vp = (float *)vpointer;
  355.  
  356.         x = vp[0];
  357.         y = vp[1];
  358.         z = vp[2];
  359.  
  360.         v->bx = a11*x + a12*y + a13*z + a14;
  361.         v->by = a21*x + a22*y + a23*z + a24;
  362.         v->bz = a31*x + a32*y + a33*z + a34;
  363.         v->bw = a41*x + a42*y + a43*z + a44;
  364.  
  365.      v++; vpointer += stride;
  366.  
  367.      } while (--i);
  368.  
  369.  
  370.      //prepare culling;
  371.  
  372.      and_code = 0xff;
  373.      or_code = 0;
  374.  
  375.      v = &context->VertexBuffer[first];
  376.  
  377.      i = size;
  378.  
  379.      do
  380.      {
  381.         cw = v->bw;
  382.         local_outcode = 0;
  383.  
  384.         if (cw < CLIP_EPS )
  385.       {
  386.                 local_outcode |= MGL_CLIP_NEGW;
  387.       }        
  388.         if (-cw > v->bx)
  389.         {
  390.                 local_outcode |= MGL_CLIP_LEFT;
  391.         }
  392.         else if (v->bx > cw)
  393.         {
  394.                 local_outcode |= MGL_CLIP_RIGHT;
  395.         }
  396.  
  397.         if (-cw > v->by)
  398.         {
  399.                 local_outcode |= MGL_CLIP_BOTTOM;
  400.         }
  401.         else if (v->by > cw)
  402.         {
  403.                 local_outcode |= MGL_CLIP_TOP;
  404.         }
  405.         
  406.         if (-cw > v->bz)
  407.         {
  408.                 local_outcode |= MGL_CLIP_BACK;
  409.         }
  410.         else if (v->bz > cw)
  411.         {
  412.                 local_outcode |= MGL_CLIP_FRONT;
  413.         }
  414.  
  415.         and_code &= local_outcode;
  416.         or_code  |= local_outcode;
  417.         v->outcode = local_outcode;
  418.  
  419.      v++;
  420.      } while (--i);
  421.  
  422.     #undef CLIP_EPS    
  423.    }
  424.  
  425.    #undef a
  426.  
  427.    if (and_code)
  428.     return -1;
  429.  
  430.    if(or_code == 0 || (or_code & context->ClipFlags))
  431.    {
  432.      return (int)or_code;
  433.    }
  434.    else
  435.    {
  436.     float gcw;
  437.     ULONG guard_code;
  438.     MGLVertex *v;
  439.  
  440.     i = size;
  441.     guard_band = 0;
  442.  
  443.     v = &context->VertexBuffer[first];
  444.  
  445.     do
  446.     {
  447.  
  448.       if(v->outcode)
  449.       {
  450.        gcw = v->bw * 2.0;
  451.       guard_code = 0;
  452.  
  453.         if (-gcw > v->bx)
  454.         {
  455.           guard_code |= MGL_CLIP_LEFT;
  456.         }
  457.         else if (v->bx > gcw)
  458.         {
  459.           guard_code |= MGL_CLIP_RIGHT;
  460.         }
  461.  
  462.         if (-gcw > v->by)
  463.         {
  464.           guard_code |= MGL_CLIP_BOTTOM;
  465.         }
  466.         else if (v->by > gcw)
  467.         {
  468.           guard_code |= MGL_CLIP_TOP;
  469.         }
  470.  
  471.       guard_band |= guard_code;
  472.         }
  473.  
  474.     v++;
  475.     } while (--i && guard_band == 0);
  476.  
  477.    return (int)guard_band;
  478.    }
  479. }
  480.  
  481.  
  482. void A_ToScreenArray(GLcontext context, const int first, const int size)
  483. {
  484.    int i, stride;
  485.    float x,y,z,w;
  486.    
  487.    UBYTE *pointer;
  488.    float *wa;
  489.    float az;
  490.  
  491.    if(context->ZOffset_State == GL_TRUE)
  492.    {
  493.        az = context->az + context->ZOffset;
  494.    }
  495.    else
  496.    {
  497.     az = context->az;
  498.    }
  499.  
  500.  
  501.    if(!(context->ClientState & GLCS_TEXTURE))
  502.    {
  503.        MGLVertex *v = &context->VertexBuffer[first];
  504.       i = size;
  505.  
  506.       do
  507.       {
  508.            x = v->bx;
  509.            y = v->by;
  510.            z = v->bz;
  511.            w = 1.0 / v->bw;
  512.         
  513.            v->bx = context->ax + x * w * context->sx;
  514.            v->by = context->ay - y * w * context->sy;
  515.            v->bz = az + z * w * context->sz;
  516.  
  517.       v++;
  518.  
  519.       } while (--i);
  520.    }
  521.    else if(context->ArrayPointer.FixpointTrans == GL_TRUE)
  522.    {
  523.        MGLVertex *v = &context->VertexBuffer[first];
  524.        stride = context->ArrayPointer.texcoordstride;
  525.        pointer = (UBYTE*)context->WBuffer + first * stride;
  526.  
  527.       i = size;
  528.  
  529.       do
  530.       {
  531.            x = v->bx;
  532.            y = v->by;
  533.            z = v->bz;
  534.            w = 1.0 / v->bw;
  535.         
  536.            v->bx = context->ax + x * w * context->sx;
  537.            v->by = context->ay - y * w * context->sy;
  538.            v->bz = az + z * w * context->sz;
  539.  
  540.          w *= 32768.f;
  541.  
  542.          wa = (float*)pointer;         
  543.          *wa = w;
  544.  
  545.       v++;
  546.       pointer += stride;
  547.  
  548.       } while (--i);    
  549.    }
  550.    else
  551.    {
  552.        MGLVertex *v = &context->VertexBuffer[first];
  553.        stride = context->ArrayPointer.texcoordstride;
  554.        pointer = (UBYTE*)context->WBuffer + first * stride;
  555.  
  556.       i = size;
  557.  
  558.       do
  559.       {
  560.            x = v->bx;
  561.            y = v->by;
  562.            z = v->bz;
  563.            w = 1.0 / v->bw;
  564.         
  565.            v->bx = context->ax + x * w * context->sx;
  566.            v->by = context->ay - y * w * context->sy;
  567.            v->bz = az + z * w * context->sz;
  568.  
  569.          wa = (float*)pointer;         
  570.          *wa = w;
  571.  
  572.       v++;
  573.       pointer += stride;
  574.       } while (--i);
  575.    }
  576. }
  577.  
  578.  
  579.  
  580. //fix to float conversion
  581.  
  582. INLINE void ConvertFixverts(GLcontext context, const int first, const int count)
  583. {
  584.     const float f = 1.0/32768.f;
  585.     MGLVertex *v = &context->VertexBuffer[first];
  586.     int i = count;
  587.  
  588.     do
  589.     {
  590.         v->bx = v->bx * f;
  591.         v->by = v->by * f;
  592.         v->bz = v->bz * f;
  593.         v->bw = v->bw * f;
  594.  
  595.     v++;
  596.     } while (--i);
  597. }
  598.  
  599.  
  600. // special case color-copy / texcoord-conversion routines
  601.  
  602.  
  603. void Convert_F_RGB(GLcontext context, int i)
  604. {
  605.    MGLVertex *v;
  606.  
  607.    v = &context->VertexBuffer[i];
  608.  
  609.    if(context->ClientState & GLCS_TEXTURE)
  610.    {
  611.    float *tex = (float*)(context->ArrayPointer.texcoords + i * context->ArrayPointer.texcoordstride);
  612.  
  613.     v->v.u = tex[0] * (float)context->w3dTexBuffer[context->CurrentBinding]->texwidth;
  614.     v->v.v = tex[1] * (float)context->w3dTexBuffer[context->CurrentBinding]->texheight;
  615.    }
  616.  
  617.    if(context->ShadeModel == GL_SMOOTH)
  618.    {
  619.    float *col = (float*)(context->ArrayPointer.colors + i * context->ArrayPointer.colorstride);;
  620.  
  621.       v->v.color.r = col[0];
  622.       v->v.color.g = col[1];
  623.       v->v.color.b = col[2];
  624.     v->v.color.a = 1.0;
  625.    }
  626. }
  627.  
  628.  
  629. void Convert_F_RGBA(GLcontext context, int i)
  630. {
  631.    MGLVertex *v;
  632.  
  633.    v = &context->VertexBuffer[i];
  634.  
  635.    if(context->ClientState & GLCS_TEXTURE)
  636.    {
  637.    float *tex = (float*)(context->ArrayPointer.texcoords + i * context->ArrayPointer.texcoordstride);
  638.  
  639.     v->v.u = tex[0] * (float)context->w3dTexBuffer[context->CurrentBinding]->texwidth;
  640.     v->v.v = tex[1] * (float)context->w3dTexBuffer[context->CurrentBinding]->texheight;
  641.    }
  642.  
  643.    if(context->ShadeModel == GL_SMOOTH)
  644.    {
  645.    float *col = (float*)(context->ArrayPointer.colors + i * context->ArrayPointer.colorstride);;
  646.  
  647.       v->v.color.r = col[0];
  648.       v->v.color.g = col[1];
  649.       v->v.color.b = col[2];
  650.       v->v.color.a = col[3];
  651.    }
  652. }
  653.  
  654.  
  655. void Convert_UB_RGB(GLcontext context, int i)
  656. {
  657.    MGLVertex *v;
  658.  
  659.    v = &context->VertexBuffer[i];
  660.  
  661.    if(context->ClientState & GLCS_TEXTURE)
  662.    {
  663.    float *tex = (float*)(context->ArrayPointer.texcoords + i * context->ArrayPointer.texcoordstride);
  664.  
  665.     v->v.u = tex[0] * (float)context->w3dTexBuffer[context->CurrentBinding]->texwidth;
  666.     v->v.v = tex[1] * (float)context->w3dTexBuffer[context->CurrentBinding]->texheight;
  667.    }
  668.  
  669.    if(context->ShadeModel == GL_SMOOTH)
  670.    {
  671.    UBYTE *col = (context->ArrayPointer.colors + i * context->ArrayPointer.colorstride);
  672.    float f = 1.0/255.0;
  673.  
  674.       v->v.color.r = (float)col[0]*f;
  675.       v->v.color.g = (float)col[1]*f;
  676.       v->v.color.b = (float)col[2]*f;
  677.       v->v.color.a = 1.0;
  678.    }
  679. }
  680.  
  681.  
  682. void Convert_UB_RGBA(GLcontext context, int i)
  683. {
  684.    MGLVertex *v;
  685.  
  686.    v = &context->VertexBuffer[i];
  687.  
  688.    if(context->ClientState & GLCS_TEXTURE)
  689.    {
  690.    float *tex = (float*)(context->ArrayPointer.texcoords + i * context->ArrayPointer.texcoordstride);
  691.  
  692.     v->v.u = tex[0] * (float)context->w3dTexBuffer[context->CurrentBinding]->texwidth;
  693.     v->v.v = tex[1] * (float)context->w3dTexBuffer[context->CurrentBinding]->texheight;
  694.    }
  695.  
  696.    if(context->ShadeModel == GL_SMOOTH)
  697.    {
  698.    UBYTE *col = (context->ArrayPointer.colors + i * context->ArrayPointer.colorstride);
  699.    float f = 1.0/255.0;
  700.  
  701.       v->v.color.r = (float)col[0]*f;
  702.       v->v.color.g = (float)col[1]*f;
  703.       v->v.color.b = (float)col[2]*f;
  704.       v->v.color.a = (float)col[3]*f;
  705.    }
  706. }
  707.  
  708.  
  709. void Convert_UB_BGR(GLcontext context, int i)
  710. {
  711.    MGLVertex *v;
  712.  
  713.    v = &context->VertexBuffer[i];
  714.  
  715.    if(context->ClientState & GLCS_TEXTURE)
  716.    {
  717.    float *tex = (float*)(context->ArrayPointer.texcoords + i * context->ArrayPointer.texcoordstride);
  718.  
  719.     v->v.u = tex[0] * (float)context->w3dTexBuffer[context->CurrentBinding]->texwidth;
  720.     v->v.v = tex[1] * (float)context->w3dTexBuffer[context->CurrentBinding]->texheight;
  721.    }
  722.  
  723.    if(context->ShadeModel == GL_SMOOTH)
  724.    {
  725.    UBYTE *col = (context->ArrayPointer.colors + i * context->ArrayPointer.colorstride);
  726.    float f = 1.0/255.0;
  727.  
  728.       v->v.color.b = (float)col[0]*f;
  729.       v->v.color.g = (float)col[1]*f;
  730.       v->v.color.r = (float)col[2]*f;
  731.       v->v.color.a = 1.0;
  732.    }
  733. }
  734.  
  735. void Convert_UB_BGRA(GLcontext context, int i)
  736. {
  737.    MGLVertex *v;
  738.  
  739.    v = &context->VertexBuffer[i];
  740.  
  741.    if(context->ClientState & GLCS_TEXTURE)
  742.    {
  743.    float *tex = (float*)(context->ArrayPointer.texcoords + i * context->ArrayPointer.texcoordstride);
  744.  
  745.     v->v.u = tex[0] * (float)context->w3dTexBuffer[context->CurrentBinding]->texwidth;
  746.     v->v.v = tex[1] * (float)context->w3dTexBuffer[context->CurrentBinding]->texheight;
  747.    }
  748.  
  749.    if(context->ShadeModel == GL_SMOOTH)
  750.    {
  751.    UBYTE *col = (context->ArrayPointer.colors + i * context->ArrayPointer.colorstride);
  752.    float f = 1.0/255.0;
  753.  
  754.       v->v.color.b = (float)col[0]*f;
  755.       v->v.color.g = (float)col[1]*f;
  756.       v->v.color.r = (float)col[2]*f;
  757.       v->v.color.a = (float)col[3]*f;
  758.    }
  759. }
  760.  
  761. void Convert_UB_ARGB(GLcontext context, int i)
  762. {
  763.    MGLVertex *v;
  764.  
  765.    v = &context->VertexBuffer[i];
  766.  
  767.    if(context->ClientState & GLCS_TEXTURE)
  768.    {
  769.    float *tex = (float*)(context->ArrayPointer.texcoords + i * context->ArrayPointer.texcoordstride);
  770.  
  771.     v->v.u = tex[0] * (float)context->w3dTexBuffer[context->CurrentBinding]->texwidth;
  772.     v->v.v = tex[1] * (float)context->w3dTexBuffer[context->CurrentBinding]->texheight;
  773.    }
  774.  
  775.    if(context->ShadeModel == GL_SMOOTH)
  776.    {
  777.    UBYTE *col = (context->ArrayPointer.colors + i * context->ArrayPointer.colorstride);
  778.    float f = 1.0/255.0;
  779.  
  780.       v->v.color.a = (float)col[0]*f;
  781.       v->v.color.r = (float)col[1]*f;
  782.       v->v.color.g = (float)col[2]*f;
  783.       v->v.color.b = (float)col[3]*f;
  784.    }
  785. }
  786.  
  787.  
  788. GLboolean DecideFrontface(GLcontext context, const MGLVertex *a, const MGLVertex *b, const MGLVertex *c, int sign)
  789. {
  790.         float a1,a2,b1,b2,r;
  791.         float aw,bw,cw;
  792.  
  793.         aw = 1.0 / a->bw;
  794.         bw = 1.0 / b->bw;
  795.         cw = 1.0 / c->bw;
  796.  
  797.         a1 = a->bx*aw - b->bx*bw;
  798.         a2 = a->by*aw - b->by*bw;
  799.         b1 = c->bx*cw - b->bx*bw;
  800.         b2 = c->by*cw - b->by*bw;
  801.  
  802.         r  = (a1*b2-a2*b1);
  803.  
  804. #if 0 //this test eliminates less than 1 in 1000 triangles
  805.  
  806.         #define EPSILON (1e-5)
  807.  
  808.         if (fabs(a1) < EPSILON && fabs(a2) < EPSILON)
  809.         {
  810.                 return GL_FALSE;
  811.         }
  812.         if (fabs(b1) < EPSILON && fabs(b2) < EPSILON)
  813.         {
  814.                 return GL_FALSE;
  815.         }
  816.  
  817. #endif
  818.  
  819.         if((sign < 0 && r < 0.0) || (sign > 0 && r > 0.0))
  820.                 return GL_FALSE;
  821.         else
  822.                 return GL_TRUE;
  823. }
  824.  
  825.  
  826. INLINE void A_ToScreen(GLcontext context, int vnum)
  827. {
  828.     UBYTE *pointer;
  829.     float *wa;
  830.  
  831.     float w = 1.0/context->VertexBuffer[vnum].bw;
  832.  
  833.     context->VertexBuffer[vnum].bx = context->ax + context->VertexBuffer[vnum].bx * w * context->sx;
  834.     context->VertexBuffer[vnum].by = context->ay - context->VertexBuffer[vnum].by * w * context->sy;
  835.     context->VertexBuffer[vnum].bz = context->az + context->VertexBuffer[vnum].bz * w * context->sz;
  836.  
  837.     if (context->ZOffset_State == GL_TRUE)
  838.         context->VertexBuffer[vnum].bz += (W3D_Float)context->ZOffset;
  839.  
  840.     pointer = (UBYTE*)context->WBuffer + vnum * context->ArrayPointer.texcoordstride;
  841.     wa = (float*)pointer;
  842.     *wa = w;
  843. }
  844.  
  845.  
  846.  
  847. //avoid double projections:
  848.  
  849. #ifdef __VBCC__
  850.  
  851. #define A_ToV(ctx, e) {\
  852. MGLVertex *v = &ctx->VertexBuffer[e];\
  853. v->v.x = v->bx;\
  854. v->v.y = v->by;\
  855. v->v.z = v->bz;\
  856. v->v.w = 1.0 / v->bw; \
  857. }
  858.  
  859. #define V_ToScreen(ctx,vnum){\
  860. static float wdiv;\
  861. wdiv = 1.0 / ctx->VertexBuffer[vnum].bw; \
  862. ctx->VertexBuffer[vnum].v.x = ctx->ax + ctx->VertexBuffer[vnum].bx * wdiv * ctx->sx; \
  863. ctx->VertexBuffer[vnum].v.y = ctx->ay - ctx->VertexBuffer[vnum].by * wdiv * ctx->sy; \
  864. ctx->VertexBuffer[vnum].v.z = ctx->az + ctx->VertexBuffer[vnum].bz * wdiv * ctx->sz; \
  865. if (ctx->ZOffset_State == GL_TRUE) ctx->VertexBuffer[vnum].v.z += (W3D_Float)ctx->ZOffset; \
  866. ctx->VertexBuffer[vnum].v.w = wdiv; \
  867. }
  868.  
  869. #else
  870.  
  871. static INLINE void A_ToV(GLcontext context, int e)
  872. {
  873.     context->VertexBuffer[e].v.x = (W3D_Float)context->VertexBuffer[e].bx;
  874.     context->VertexBuffer[e].v.y = (W3D_Float)context->VertexBuffer[e].by;
  875.     context->VertexBuffer[e].v.z = (W3D_Float)context->VertexBuffer[e].bz;
  876.     context->VertexBuffer[e].v.w = (W3D_Float)(1.0 / context->VertexBuffer[e].bw);
  877. }
  878.  
  879. static INLINE void V_ToScreen(GLcontext context, int vnum)
  880. {
  881.     GLfloat wdiv = 1.f / context->VertexBuffer[vnum].bw;
  882.  
  883.     context->VertexBuffer[vnum].v.x = (W3D_Float)(context->ax + context->VertexBuffer[vnum].bx * wdiv * context->sx);
  884.  
  885.     context->VertexBuffer[vnum].v.y = (W3D_Float)(context->ay - context->VertexBuffer[vnum].by * wdiv * context->sy);
  886.  
  887.     context->VertexBuffer[vnum].v.z = (W3D_Float)(context->az + context->VertexBuffer[vnum].bz * wdiv * context->sz);
  888.  
  889.     if (context->ZOffset_State == GL_TRUE) context->VertexBuffer[vnum].v.z += (W3D_Float)context->ZOffset; \
  890.  
  891.     context->VertexBuffer[vnum].v.w = (W3D_Float)wdiv; \
  892. }
  893.  
  894. #endif
  895.  
  896.  
  897. void A_DrawPoints(GLcontext context, const int first, const int count)
  898. {
  899. }
  900.  
  901.  
  902. void A_DrawLines(GLcontext context, const int first, const int count)
  903. {
  904. }
  905.  
  906.  
  907. void A_DrawLineStrip(GLcontext context, const int first, const int count)
  908. {
  909. }
  910.  
  911.  
  912. void A_DrawLineLoop(GLcontext context, const int first, const int count)
  913. {
  914. }
  915.  
  916.  
  917. void A_DrawQuads(GLcontext context, const int first, const int count)
  918. {
  919. }
  920.  
  921.  
  922. void A_DrawQuadStrip(GLcontext context, const int first, const int count)
  923. {
  924. }
  925.  
  926.  
  927. void A_DrawTriFan(GLcontext context, const int first, const int count)
  928. {
  929.       int i,j;
  930.     int size;
  931.     int outcode;
  932.       ULONG local_or, local_and;
  933.       ULONG error;
  934.       static W3D_Vertex **verts = NULL;
  935.       static W3D_TrianglesV fan;
  936.       static ULONG    complete[MGL_MAXVERTS];
  937.       static GLboolean visible[MGL_MAXVERTS];
  938.       int triangle;
  939.       static PolyBuffer polys[64];
  940.       PolyBuffer clip[64];
  941.       int pnum, cnum, backface, prevcopy, free;
  942.       int sign;
  943.  
  944.  
  945.     if(Clip_Volume_Bypass != GL_FALSE)
  946.     {
  947.     //compiled arrays
  948.  
  949.        size = count;
  950.  
  951.        //first check if we are in guardband-mode
  952.        //and discard/shrink offscreen primitives
  953.  
  954.        if(Clip_Volume_Bypass == GL_TRUE + 1)
  955.        {
  956.         i = first + size - 2;
  957.  
  958.         do            
  959.         {
  960.             local_and = context->VertexBuffer[first].outcode & context->VertexBuffer[i].outcode & context->VertexBuffer[i+1].outcode;
  961.  
  962.             if(local_and == 0)
  963.                 break;
  964.  
  965.         size--;
  966.         i--;
  967.         } while (i > first);
  968.  
  969.         if(size < 3)
  970.             return;
  971.        }
  972.  
  973.        if(context->CullFace_State == GL_FALSE)
  974.        {
  975.         error = W3D_DrawArray(context->w3dContext, W3D_PRIMITIVE_TRIFAN, first, size);
  976.        }
  977.        else
  978.        {
  979.        int newfirst;
  980.        float fsign;
  981.        float area;
  982.        float x1,x2;
  983.        float y1,y2;
  984.  
  985.        #define x(a) (context->VertexBuffer[first+a].bx)
  986.        #define y(a) (context->VertexBuffer[first+a].by)
  987.  
  988.         fsign = (float)-context->CurrentCullSign;
  989.  
  990.         backface = 0;
  991.         newfirst = 0;
  992.  
  993.               if(size == 3)
  994.             {
  995.                   x1 = x(1) - x(0);
  996.                   y1 = y(1) - y(0);
  997.                   x2 = x(2) - x(0);
  998.                   y2 = y(2) - y(0);
  999.  
  1000.                   area = y2*x1 - x2*y1;
  1001.                   area *= fsign;
  1002.         }
  1003.         else
  1004.         {
  1005.             float x0,y0;
  1006.             float area2;
  1007.  
  1008.                   x0 = x(0);
  1009.                   y0 = y(0);
  1010.      
  1011.                   x1 = x(1) - x0;
  1012.                   y1 = y(1) - y0;
  1013.                   x2 = x(2) - x0;
  1014.                     y2 = y(2) - y0;
  1015.  
  1016.                     area = y2*x1 - x2*y1;
  1017.               area *= fsign;
  1018.  
  1019.                        if(area < 0.f)
  1020.                        {
  1021.                             newfirst++;
  1022.                             area = 0.f;
  1023.                        }
  1024.         
  1025.                        i = 1;
  1026.                        do
  1027.                        {
  1028.                          x1 = x2;
  1029.                            y1 = y2;
  1030.                            x2 = x(i+2) - x0;
  1031.                            y2 = y(i+2) - y0;
  1032.  
  1033.                            area2 = y2*x1 - x2*y1;
  1034.                            area2 *= fsign;
  1035.     
  1036.                               if(area2 < 0.f)
  1037.                               {
  1038.                   if(newfirst == i)
  1039.                     newfirst++;
  1040.                   else
  1041.                                       backface++;
  1042.                             }
  1043.                             else
  1044.                               {
  1045.                                 backface = 0;
  1046.                                 area += area2;
  1047.                               }
  1048.  
  1049.                     i++;
  1050.                     } while (i < size-2);
  1051.         }
  1052.  
  1053.         if(area < context->MinTriArea)
  1054.         return;
  1055.  
  1056.         size -= backface; //cut end
  1057.  
  1058.         if( newfirst )
  1059.         {
  1060.         
  1061.             size -= newfirst;
  1062.             newfirst += first;
  1063.  
  1064.             e_wrap[newfirst] = first;
  1065.  
  1066.             error = W3D_DrawElements(context->w3dContext, W3D_PRIMITIVE_TRIFAN, W3D_INDEX_UWORD, size, (void*)&(e_wrap[newfirst]));
  1067.  
  1068.             e_wrap[newfirst] = newfirst;
  1069.         }
  1070.         else
  1071.         {
  1072.             error = W3D_DrawArray(context->w3dContext, W3D_PRIMITIVE_TRIFAN, first, size);
  1073.         }
  1074.        #undef x
  1075.        #undef y
  1076.        }
  1077.     return;
  1078.     }
  1079.  
  1080.     sign = context->CurrentCullSign;
  1081.  
  1082.     outcode = A_TransformArray(context, first, count);
  1083.     
  1084.  
  1085.       if(outcode < 0)
  1086.       {
  1087.         return;
  1088.       }
  1089.  
  1090.       if (outcode == 0)
  1091.       {
  1092.         size = count;
  1093.  
  1094.         A_ToScreenArray(context, first, count);
  1095.  
  1096.         if(context->CullFace_State == GL_TRUE)
  1097.         {
  1098.         int newfirst;
  1099.         float fsign;
  1100.         float area;
  1101.         float x1,x2;
  1102.         float y1,y2;
  1103.  
  1104.         #define x(a) (context->VertexBuffer[first+a].bx)
  1105.         #define y(a) (context->VertexBuffer[first+a].by)
  1106.  
  1107.         fsign = (float)-sign;
  1108.  
  1109.         backface = 0;
  1110.         newfirst = 0;
  1111.  
  1112.  
  1113.                     if(size == 3)
  1114.                   {
  1115.                         x1 = x(1) - x(0);
  1116.                         y1 = y(1) - y(0);
  1117.                         x2 = x(2) - x(0);
  1118.                         y2 = y(2) - y(0);
  1119.  
  1120.                         area = y2*x1 - x2*y1;
  1121.                         area *= fsign;
  1122.               }
  1123.               else
  1124.               {
  1125.                   float x0,y0;
  1126.                   float area2;
  1127.  
  1128.                         x0 = x(0);
  1129.                         y0 = y(0);
  1130.      
  1131.                         x1 = x(1) - x0;
  1132.                         y1 = y(1) - y0;
  1133.                         x2 = x(2) - x0;
  1134.                         y2 = y(2) - y0;
  1135.  
  1136.                         area = y2*x1 - x2*y1;
  1137.                   area *= fsign;
  1138.  
  1139.                            if(area < 0.f)
  1140.                            {
  1141.                             newfirst++;
  1142.                             area = 0.f;
  1143.                            }
  1144.         
  1145.                            i = 1;
  1146.                            do
  1147.                            {
  1148.                          x1 = x2;
  1149.                            y1 = y2;
  1150.                            x2 = x(i+2) - x0;
  1151.                            y2 = y(i+2) - y0;
  1152.  
  1153.                            area2 = y2*x1 - x2*y1;
  1154.                            area2 *= fsign;
  1155.     
  1156.                               if(area2 < 0.f)
  1157.                               {
  1158.                   if(newfirst == i)
  1159.                     newfirst++;
  1160.                   else
  1161.                                       backface++;
  1162.                             }
  1163.                             else
  1164.                               {
  1165.                                 backface = 0;
  1166.                                 area += area2;
  1167.                               }
  1168.  
  1169.                            i++;
  1170.                            } while (i < size-2);
  1171.             }
  1172.  
  1173.             if(area < context->MinTriArea)
  1174.             return;
  1175.  
  1176.             size -= backface; //cut end
  1177.  
  1178.             if( newfirst )
  1179.             {
  1180.                 size -= newfirst;
  1181.                 newfirst += first;
  1182.  
  1183.                 e_wrap[newfirst] = first;
  1184.  
  1185.                 error = W3D_DrawElements(context->w3dContext, W3D_PRIMITIVE_TRIFAN, W3D_INDEX_UWORD, size, (void*)&(e_wrap[newfirst]));
  1186.  
  1187.                 e_wrap[newfirst] = newfirst;
  1188.  
  1189.                 return;
  1190.             }
  1191.  
  1192.         #undef x
  1193.         #undef y
  1194.         }
  1195.  
  1196.         error = W3D_DrawArray(context->w3dContext, W3D_PRIMITIVE_TRIFAN, first, size);
  1197.  
  1198.       return;
  1199.       }
  1200.  
  1201.  
  1202.         if (verts == NULL)
  1203.         {
  1204.                 verts = (W3D_Vertex **)malloc(sizeof(W3D_Vertex *) * context->VertexBufferSize);
  1205.                 if (!verts) return;
  1206.         }
  1207.  
  1208.       if(context->ArrayPointer.FixpointTrans == GL_TRUE)
  1209.       {
  1210.         ConvertFixverts(context, first, count);
  1211.       }
  1212.  
  1213.         backface = 0;
  1214.         triangle = 0;
  1215.         i = first+1;
  1216.  
  1217.    if(context->CullFace_State == GL_FALSE)
  1218.    {
  1219.         do
  1220.         {
  1221.                 local_and = context->VertexBuffer[first].outcode
  1222.                         & context->VertexBuffer[i].outcode
  1223.                         & context->VertexBuffer[i+1].outcode;
  1224.  
  1225.                 local_or = context->VertexBuffer[first].outcode
  1226.                         | context->VertexBuffer[i].outcode
  1227.                         | context->VertexBuffer[i+1].outcode;
  1228.  
  1229.  
  1230.                 if (local_and == 0) // if the local and code is zero, we're not
  1231.                 {
  1232.                     complete[triangle] = local_or;
  1233.                       visible[triangle] = GL_TRUE;
  1234.             backface = 0;
  1235.                 }
  1236.                 else
  1237.                 {
  1238.                         visible[triangle] = GL_FALSE;    
  1239.                         backface++;
  1240.                 }
  1241.            i++;
  1242.            triangle++;
  1243.         } while (triangle < count - 2);
  1244.    }
  1245.    else
  1246.    {
  1247.         do
  1248.         {
  1249.                 local_and = context->VertexBuffer[first].outcode
  1250.                         & context->VertexBuffer[i].outcode
  1251.                         & context->VertexBuffer[i+1].outcode;
  1252.  
  1253.                 local_or = context->VertexBuffer[first].outcode
  1254.                         | context->VertexBuffer[i].outcode
  1255.                         | context->VertexBuffer[i+1].outcode;
  1256.  
  1257.  
  1258.                 if (local_and == 0) // if the local and code is zero, we're not
  1259.                 {
  1260.              complete[triangle] = local_or;
  1261.  
  1262.                    if(local_or & MGL_CLIP_NEGW)
  1263.                    {
  1264.                         visible[triangle] = GL_TRUE;
  1265.               backface = 0;
  1266.                    }
  1267.                    else
  1268.                    {
  1269.                         visible[triangle] = DecideFrontface(context, &(context->VertexBuffer[first]), &(context->VertexBuffer[i]), &(context->VertexBuffer[i+1]), sign);
  1270.  
  1271.                         if(!visible[triangle])
  1272.                             backface++;
  1273.               else
  1274.                   backface = 0;
  1275.                    }
  1276.                 }
  1277.                 else
  1278.                 {
  1279.                         visible[triangle] = GL_FALSE;    
  1280.                         backface++;
  1281.                 }
  1282.            i++;
  1283.            triangle++;
  1284.         } while (triangle < count - 2);
  1285.    }
  1286.  
  1287.  
  1288.         if(backface == triangle) //early out
  1289.         return;
  1290.  
  1291.       size = count - backface;
  1292.       context->VertexBufferPointer -= backface;
  1293.  
  1294.            Convert(context, first);
  1295.  
  1296.         prevcopy = 0;
  1297.         pnum = 0;
  1298.         cnum = 0;
  1299.         free = context->VertexBufferPointer;
  1300.         triangle = 0; i = first + 1;
  1301.  
  1302.         do
  1303.         {
  1304.                 if (visible[triangle] == GL_FALSE) // case 3
  1305.                 {
  1306.                         triangle ++;
  1307.                         i        ++;
  1308.                 }
  1309.                 else
  1310.                 {
  1311.                         if (complete[triangle]) // case 1
  1312.                         {
  1313.                                 clip[cnum].numverts = 3;
  1314.                                 clip[cnum].verts[0] = first;
  1315.                                 clip[cnum].verts[1] = i + 0;
  1316.                                 clip[cnum].verts[2] = i + 1;
  1317.  
  1318.                                 if(prevcopy != i)
  1319.                                 Convert(context, i+0);
  1320.  
  1321.                                 Convert(context, i+1);
  1322.  
  1323.                                 prevcopy = i+1;
  1324.  
  1325.                            AE_ClipPoly(context, &clip[cnum], free, complete[triangle]);
  1326.  
  1327.                            if(clip[cnum].numverts)
  1328.                            {
  1329.  
  1330.                                free = clip[cnum].nextfree;
  1331.                                cnum++;
  1332.                            }
  1333.  
  1334.                            triangle++; i++;
  1335.  
  1336.  
  1337.                         }
  1338.                         else
  1339.                         {   // case 2 (the difficult part)
  1340.                                 int k=3;
  1341.                                 polys[pnum].verts[0] = first;
  1342.                                 polys[pnum].verts[1] = i+0;
  1343.                                 polys[pnum].verts[2] = i+1;
  1344.         
  1345.                                 triangle++; i++;
  1346.  
  1347.                                 while (complete[triangle]==0 && visible[triangle] && triangle < size - 2)
  1348.                                 {
  1349.                                 polys[pnum].verts[k] = i+1;
  1350.  
  1351.                                 i++; k++; triangle++;
  1352.                                 }
  1353.                         polys[pnum].numverts = k;
  1354.                         pnum++;
  1355.                         }
  1356.                 }
  1357.         } while (triangle < size - 2);
  1358.  
  1359. //Project to screen and draw:
  1360.  
  1361.    //avoid some double-projections
  1362.  
  1363.    if(cnum)
  1364.    {
  1365.    for(i=0; i<size; i++)
  1366.     visible[first+i] = 0;
  1367.  
  1368.    //project clipped verts without index lookup
  1369.  
  1370.       for(i=context->VertexBufferPointer; i<free; i++)
  1371.     {
  1372.           V_ToScreen(context, i);
  1373.     }
  1374.    }
  1375.  
  1376.    if(pnum) //draw buffered unclipped trifans
  1377.    {
  1378.         PolyBuffer *p;
  1379.  
  1380.         p = &polys[0];
  1381.         i = p->verts[1];
  1382.  
  1383.         A_ToScreen(context, first);
  1384.         A_ToScreen(context, i);
  1385.         A_ToScreen(context, i+1);
  1386.  
  1387.         visible[first] = 1;
  1388.         visible[i] = 1;
  1389.         visible[i+1] = 1;
  1390.  
  1391.         if(p->numverts > 3)
  1392.         {
  1393.         int last = p->verts[p->numverts-1];
  1394.         i+=2;
  1395.                 do
  1396.                 {
  1397.                         A_ToScreen(context, i);
  1398.                         visible[i] = 1;
  1399.                 i++;
  1400.                 } while (i <= last);
  1401.         }
  1402.  
  1403.         if(p->verts[1] == (first+1))
  1404.         {
  1405.         error = W3D_DrawArray(context->w3dContext, W3D_PRIMITIVE_TRIFAN, first, p->numverts);
  1406.         }
  1407.         else
  1408.         {
  1409.         error = W3D_DrawElements(context->w3dContext, W3D_PRIMITIVE_TRIFAN, W3D_INDEX_ULONG, p->numverts, (void*)p->verts);
  1410.         }
  1411.  
  1412.         j = 1;
  1413.         while (j < pnum)
  1414.         {
  1415.                 p = &polys[j];
  1416.                 i = p->verts[1];
  1417.  
  1418.                 A_ToScreen(context, i);
  1419.                 A_ToScreen(context, i+1);
  1420.  
  1421.                 visible[i] = 1;
  1422.                 visible[i+1] = 1;
  1423.  
  1424.                 if(p->numverts > 3)
  1425.                 {
  1426.                 int last = p->verts[p->numverts-1];
  1427.                 i+=2;
  1428.  
  1429.                    do
  1430.                    {
  1431.                         A_ToScreen(context, i);
  1432.                         visible[i] = 1;
  1433.                    i++;
  1434.                    } while (i <= last);
  1435.                 }
  1436.  
  1437.         error = W3D_DrawElements(context->w3dContext, W3D_PRIMITIVE_TRIFAN, W3D_INDEX_ULONG, p->numverts, (void*)p->verts);
  1438.  
  1439.         j++;
  1440.         }
  1441.    }
  1442.  
  1443.    if(cnum) //draw clipped triangles
  1444.    {
  1445.    int first = 0;
  1446.  
  1447.    fan.tex = context->w3dTexBuffer[context->CurrentBinding];
  1448.    fan.st_pattern = 0;
  1449.  
  1450.      j = 0;
  1451.      do
  1452.      {
  1453.           PolyBuffer *p = &clip[j];
  1454.  
  1455.           for (i=0; i<p->numverts; i++)
  1456.           {
  1457.                 int vert = p->verts[i];
  1458.  
  1459.                 if(vert < context->VertexBufferPointer)
  1460.                 {
  1461.                    switch(visible[vert])
  1462.                    {
  1463.                         case 2:
  1464.                                 break;
  1465.                         case 1:
  1466.                                 A_ToV(context, vert);
  1467.                                 visible[vert] = 2;
  1468.                                 break;
  1469.                         default:
  1470.                                 V_ToScreen(context, vert);
  1471.                                 visible[vert] = 2;
  1472.                                 break;
  1473.                    }
  1474.                 }
  1475.  
  1476.           verts[i+first] = &(context->VertexBuffer[vert].v);
  1477.           }
  1478.  
  1479.           fan.vertexcount = p->numverts;
  1480.           fan.v = &verts[first];
  1481.  
  1482.           error = W3D_DrawTriFanV(context->w3dContext, &fan);
  1483.  
  1484.           first += p->numverts;
  1485.  
  1486.         j++;
  1487.       } while (j < cnum);
  1488.    }
  1489. }
  1490.  
  1491.  
  1492. void A_DrawTriStrip(GLcontext context, const int first, const int count)
  1493. {
  1494.       int i,j;
  1495.     int size;
  1496.     int outcode;
  1497.       ULONG local_or, local_and;
  1498.       ULONG error;
  1499.       static W3D_Vertex **verts = NULL;
  1500.       static W3D_TrianglesV fan;
  1501.       static GLboolean visible[MGL_MAXVERTS];
  1502.       static ULONG    complete[MGL_MAXVERTS];
  1503.       int triangle;
  1504.       static PolyBuffer polys[64];
  1505.       PolyBuffer clip[64];
  1506.       int pnum, cnum, backface, free, prevcopy;
  1507.       int sign;
  1508.  
  1509.     if(Clip_Volume_Bypass != GL_FALSE)
  1510.     {
  1511.     //compiled arrays
  1512.     size = count;
  1513.  
  1514.        //first check if we are in guardband-mode
  1515.        //and discard/shrink offscreen primitives
  1516.  
  1517.        if(Clip_Volume_Bypass == GL_TRUE + 1)
  1518.        {
  1519.         i = first + size - 3;
  1520.         do            
  1521.         {
  1522.             local_and = context->VertexBuffer[i].outcode & context->VertexBuffer[i+1].outcode & context->VertexBuffer[i+2].outcode;
  1523.  
  1524.             if(local_and == 0)
  1525.                 break;
  1526.  
  1527.         size--;
  1528.         i--;
  1529.         } while (i >= first);
  1530.  
  1531.         if(size < 3)
  1532.             return;
  1533.        }
  1534.  
  1535.        if(context->CullFace_State == GL_FALSE)
  1536.        {
  1537.         error = W3D_DrawArray(context->w3dContext, W3D_PRIMITIVE_TRISTRIP, first, size);
  1538.        }
  1539.        else
  1540.        {
  1541.        int newfirst;
  1542.        float fsign;
  1543.        float area;
  1544.        float x1,x2;
  1545.        float y1,y2;
  1546.  
  1547.        #define x(a) (context->VertexBuffer[first+a].bx)
  1548.        #define y(a) (context->VertexBuffer[first+a].by)
  1549.  
  1550.         fsign = (float)-context->CurrentCullSign;
  1551.  
  1552.         backface = 0;
  1553.         newfirst = 0;
  1554.  
  1555.                  if(size == 3)
  1556.             {
  1557.                      x1 = x(1) - x(0);
  1558.                      y1 = y(1) - y(0);
  1559.                      x2 = x(2) - x(0);
  1560.                      y2 = y(2) - y(0);
  1561.  
  1562.                      area = y2*x1 - x2*y1;
  1563.                      area *= fsign;
  1564.           }
  1565.           else
  1566.           {
  1567.               float a1,a2,b1,b2;
  1568.               float area2;
  1569.  
  1570.                      a1 = x(1);
  1571.                      b1 = y(1);
  1572.                      a2 = x(2);
  1573.                      b2 = y(2);
  1574.  
  1575.                      x1 = a1 - x(0);
  1576.                      y1 = b1 - y(0);
  1577.                      x2 = a2 - x(0);
  1578.                      y2 = b2 - y(0);
  1579.  
  1580.                      area = y2*x1 - x2*y1;
  1581.              area *= fsign;
  1582.  
  1583.                         if(area < 0.f)
  1584.                         {
  1585.                              newfirst++;
  1586.                              area = 0.f;
  1587.                         }
  1588.         
  1589.                         i = 1;
  1590.                         do
  1591.                     {
  1592.                            fsign = -fsign;
  1593.                            x1 = a2 - a1;
  1594.                            y1 = b2 - b1;
  1595.                            x2 = x(i+2) - a1;
  1596.                            y2 = y(i+2) - b1;
  1597.                            a1 = a2;
  1598.                           b1 = b2;
  1599.                            a2 = x(i+2);
  1600.                            b2 = y(i+2);
  1601.  
  1602.                            area2 = y2*x1 - x2*y1;
  1603.                 area2 *= fsign;
  1604.     
  1605.                 if(area2 < 0.f)
  1606.                 {
  1607.                   if(newfirst == i)
  1608.                     newfirst++;
  1609.                   else
  1610.                                       backface++;
  1611.                 }
  1612.                 else
  1613.                  {
  1614.                                 backface = 0;
  1615.                                 area += area2;
  1616.                 }
  1617.  
  1618.                      i++;
  1619.               } while (i < size-2);
  1620.         }
  1621.  
  1622.        if(area < context->MinTriArea)
  1623.         return;
  1624.  
  1625.        size -= newfirst + backface;
  1626.        newfirst += first;
  1627.  
  1628.        error = W3D_DrawArray(context->w3dContext, W3D_PRIMITIVE_TRISTRIP, newfirst, size);
  1629.  
  1630.        #undef x
  1631.        #undef y
  1632.        }
  1633.     return;
  1634.     }
  1635.  
  1636.     sign = context->CurrentCullSign;
  1637.  
  1638.     outcode = A_TransformArray(context, first, count);
  1639.  
  1640.       if (outcode < 0)
  1641.       {
  1642.         return;
  1643.       }
  1644.  
  1645.       if (outcode == 0)
  1646.       {
  1647.         int newfirst;
  1648.         size = count;
  1649.  
  1650.         A_ToScreenArray(context, first, count);
  1651.  
  1652.         if(context->CullFace_State == GL_FALSE)
  1653.         {
  1654.             newfirst = first;
  1655.         }
  1656.         else
  1657.         {
  1658.         #define x(a) (context->VertexBuffer[first+a].bx)
  1659.         #define y(a) (context->VertexBuffer[first+a].by)
  1660.  
  1661.         float fsign;
  1662.         float area;
  1663.         float x1,x2;
  1664.         float y1,y2;
  1665.  
  1666.         fsign = (float)-sign;
  1667.  
  1668.         backface = 0;
  1669.         newfirst = 0;
  1670.  
  1671.  
  1672.                     if(size == 3)
  1673.                   {
  1674.                         x1 = x(1) - x(0);
  1675.                         y1 = y(1) - y(0);
  1676.                         x2 = x(2) - x(0);
  1677.                         y2 = y(2) - y(0);
  1678.  
  1679.                         area = y2*x1 - x2*y1;
  1680.                         area *= fsign;
  1681.               }
  1682.               else
  1683.               {
  1684.                   float a1,a2,b1,b2;
  1685.                   float area2;
  1686.  
  1687.                         a1 = x(1);
  1688.                         b1 = y(1);
  1689.                         a2 = x(2);
  1690.                         b2 = y(2);
  1691.  
  1692.                         x1 = a1 - x(0);
  1693.                         y1 = b1 - y(0);
  1694.                         x2 = a2 - x(0);
  1695.                         y2 = b2 - y(0);
  1696.  
  1697.                         area = y2*x1 - x2*y1;
  1698.                   area *= fsign;
  1699.  
  1700.                            if(area < 0.f)
  1701.                            {
  1702.                             newfirst++;
  1703.                             area = 0.f;
  1704.                            }
  1705.         
  1706.                            i = 1;
  1707.                            do
  1708.                            {
  1709.                            fsign = -fsign;
  1710.                            x1 = a2 - a1;
  1711.                            y1 = b2 - b1;
  1712.                            x2 = x(i+2) - a1;
  1713.                            y2 = y(i+2) - b1;
  1714.                            a1 = a2;
  1715.                           b1 = b2;
  1716.                            a2 = x(i+2);
  1717.                            b2 = y(i+2);
  1718.  
  1719.                            area2 = y2*x1 - x2*y1;
  1720.                            area2 *= fsign;
  1721.     
  1722.                               if(area2 < 0.f)
  1723.                               {
  1724.                   if(newfirst == i)
  1725.                     newfirst++;
  1726.                   else
  1727.                                       backface++;
  1728.                             }
  1729.                             else
  1730.                               {
  1731.                                 backface = 0;
  1732.                                 area += area2;
  1733.                               }
  1734.  
  1735.                            i++;
  1736.                            } while (i < size-2);
  1737.             }
  1738.  
  1739.         if(area < context->MinTriArea)
  1740.             return;
  1741.  
  1742.         size -= newfirst + backface;
  1743.         newfirst += first;
  1744.  
  1745.         #undef x
  1746.         #undef y
  1747.         }
  1748.     
  1749.            error = W3D_DrawArray(context->w3dContext, W3D_PRIMITIVE_TRISTRIP, newfirst, size);
  1750.  
  1751.       return;
  1752.       }
  1753.  
  1754.         if (verts == NULL)
  1755.         {
  1756.                 verts = (W3D_Vertex **)malloc(sizeof(W3D_Vertex *) * context->VertexBufferSize);
  1757.                 if (!verts) return;
  1758.         }
  1759.  
  1760.       if(context->ArrayPointer.FixpointTrans == GL_TRUE)
  1761.       {
  1762.         ConvertFixverts(context, first, count);
  1763.       }
  1764.  
  1765.  
  1766.         backface = 0;
  1767.         triangle = 0;
  1768.         i = first;
  1769.  
  1770.    if(context->CullFace_State == GL_FALSE)
  1771.    {
  1772.         do
  1773.         {
  1774.                 local_and = context->VertexBuffer[i+0].outcode
  1775.                                   & context->VertexBuffer[i+1].outcode
  1776.                                   & context->VertexBuffer[i+2].outcode;
  1777.  
  1778.                 local_or = context->VertexBuffer[i+0].outcode
  1779.                                  | context->VertexBuffer[i+1].outcode
  1780.                                  | context->VertexBuffer[i+2].outcode;
  1781.  
  1782.                 if (local_and == 0)
  1783.                 {
  1784.             complete[triangle] = local_or;
  1785.             visible[triangle] = GL_TRUE;
  1786.             backface = 0;
  1787.                 }
  1788.                 else
  1789.                 {
  1790.                         visible[triangle] = GL_FALSE;
  1791.                         backface++;
  1792.                 }
  1793.  
  1794.            i++;
  1795.            triangle++;
  1796.         } while (triangle < count - 2);
  1797.    }
  1798.    else
  1799.    {
  1800.         do
  1801.         {
  1802.                 local_and = context->VertexBuffer[i+0].outcode
  1803.                                   & context->VertexBuffer[i+1].outcode
  1804.                                   & context->VertexBuffer[i+2].outcode;
  1805.  
  1806.                 local_or = context->VertexBuffer[i+0].outcode
  1807.                                  | context->VertexBuffer[i+1].outcode
  1808.                                  | context->VertexBuffer[i+2].outcode;
  1809.  
  1810.                 if (local_and == 0)
  1811.                 {
  1812.                 complete[triangle] = local_or;
  1813.  
  1814.                    if(local_or & MGL_CLIP_NEGW)
  1815.                    {
  1816.                         visible[triangle] = GL_TRUE;
  1817.               backface = 0;
  1818.                    }
  1819.                    else
  1820.                    {
  1821.                         visible[triangle] = DecideFrontface(context, &(context->VertexBuffer[i+0]), &(context->VertexBuffer[i+1]), &(context->VertexBuffer[i+2]), sign);
  1822.  
  1823.                         if(!visible[triangle])
  1824.                             backface++;
  1825.               else
  1826.                   backface = 0;
  1827.                    }
  1828.                 }
  1829.                 else
  1830.                 {
  1831.                         visible[triangle] = GL_FALSE;
  1832.                         backface++;
  1833.                 }
  1834.  
  1835.                 sign = -sign; //reverse order
  1836.  
  1837.            i++;
  1838.            triangle++;
  1839.         } while (triangle < count - 2);
  1840.    }
  1841.  
  1842.     if(backface == triangle) //early out
  1843.     return;
  1844.  
  1845.     size = count - backface;
  1846.     context->VertexBufferPointer -= backface;
  1847.  
  1848.     prevcopy = -1;
  1849.       pnum = 0;
  1850.       cnum = 0;
  1851.       free = context->VertexBufferPointer;
  1852.       triangle = 0; i=first;
  1853.  
  1854.         do
  1855.         {
  1856.                 if (visible[triangle] == GL_FALSE) // case 3
  1857.                 {
  1858.                         triangle++; i++;
  1859.                 }
  1860.                 else
  1861.                 {
  1862.                         if (complete[triangle]) // case 1
  1863.                         {
  1864.                                 clip[cnum].numverts = 3;
  1865.                                 clip[cnum].verts[0] = i + 0;
  1866.                                 clip[cnum].verts[1] = i + 1;
  1867.                                 clip[cnum].verts[2] = i + 2;
  1868.  
  1869. //this element is never shared with next triangle:
  1870.                                 if(prevcopy == i+1)
  1871.                                 {
  1872.                                    Convert(context, i+2);
  1873.                                 }
  1874.  
  1875.                                 else if(prevcopy == i)
  1876.                                 {
  1877.                                    Convert(context, i+1);
  1878.                                    Convert(context, i+2);
  1879.                                 }
  1880.                   else
  1881.                   {
  1882.                                    Convert(context, i+0);
  1883.                                    Convert(context, i+1);
  1884.                                    Convert(context, i+2);
  1885.                   }
  1886.  
  1887. //this element is never shared with previous triangle:
  1888.  
  1889.                                 prevcopy = i+2;
  1890.  
  1891.                            AE_ClipPoly(context, &clip[cnum], free, complete[triangle]);
  1892.  
  1893.                            if(clip[cnum].numverts)
  1894.                            {
  1895.                            free = clip[cnum].nextfree;
  1896.                            cnum++;
  1897.                            }
  1898.  
  1899.                            triangle++; i++;
  1900.  
  1901.                         }
  1902.                         else
  1903.                         {   // case 2 (the difficult part)
  1904.                                 int k=3;
  1905.                                 polys[pnum].verts[0] = i+0;
  1906.                                 //polys[pnum].verts[1] = i+1;
  1907.                                 //polys[pnum].verts[2] = i+2;
  1908.  
  1909.                                 triangle++; i++;
  1910.  
  1911.                                 while (visible[triangle] && complete[triangle]==0 && triangle < size - 2 && k < 64)
  1912.                                 {
  1913.                                 //polys[pnum].verts[k] = i+2;
  1914.  
  1915.                                 i++; k++; triangle++;
  1916.                                 }
  1917.                         polys[pnum].numverts = k;
  1918.                         pnum++;
  1919.                         }
  1920.                 }
  1921.         } while (triangle < size - 2);
  1922.  
  1923.  
  1924.  
  1925. //Project to screen and Draw:
  1926.  
  1927.    //avoid some double-projections
  1928.  
  1929.    if(cnum)
  1930.    {
  1931.    for(i=0; i < size; i++)
  1932.     visible[first+i] = 0;
  1933.  
  1934.    //project clipped verts without need for index lookup
  1935.  
  1936.       for(i=context->VertexBufferPointer; i<free; i++)
  1937.       {
  1938.           V_ToScreen(context, i);
  1939.       }
  1940.    }
  1941.  
  1942.    if(pnum) //draw buffered unclipped tristrips
  1943.    {
  1944.         PolyBuffer *p;
  1945.  
  1946.         p = &polys[0];
  1947.         i = p->verts[0];
  1948.  
  1949.         A_ToScreen(context, i);
  1950.         A_ToScreen(context, i+1);
  1951.         A_ToScreen(context, i+2);
  1952.  
  1953.         visible[i] = 1;
  1954.         visible[i+1] = 1;
  1955.         visible[i+2] = 1;
  1956.  
  1957.         if(p->numverts > 3)
  1958.         {
  1959.         int last = p->numverts + i;
  1960.         i+=3;
  1961.  
  1962.                 do
  1963.                 {
  1964.                         A_ToScreen(context, i);
  1965.                         visible[i] = 1;
  1966.                 i++;
  1967.                 } while (i < last);
  1968.         }
  1969.  
  1970.         error = W3D_DrawArray(context->w3dContext, W3D_PRIMITIVE_TRISTRIP, p->verts[0], p->numverts);
  1971.  
  1972.         j = 1;
  1973.         while (j < pnum)
  1974.         {
  1975.         int prev_projected = p->verts[0] + p->numverts-1;
  1976.  
  1977.                 p = &polys[j];
  1978.                 i = p->verts[0];
  1979.  
  1980.                 if (i != prev_projected)
  1981.                 {
  1982.                         A_ToScreen(context, i);
  1983.                         visible[i] = 1;
  1984.                 }
  1985.  
  1986.                 A_ToScreen(context, i+1);
  1987.                 A_ToScreen(context, i+2);
  1988.  
  1989.                 visible[i+1] = 1;
  1990.                 visible[i+2] = 1;
  1991.  
  1992.                 if(p->numverts > 3)
  1993.                 {               
  1994.                 int last = i + p->numverts;
  1995.                 i+=3;
  1996.  
  1997.                    do
  1998.                    {
  1999.                         A_ToScreen(context, i);
  2000.                         visible[i] = 1;
  2001.                    i++;
  2002.                    } while (i < last);
  2003.                 }
  2004.  
  2005.         error = W3D_DrawArray(context->w3dContext, W3D_PRIMITIVE_TRISTRIP, p->verts[0], p->numverts);
  2006.  
  2007.         j++;
  2008.         }
  2009.    }
  2010.  
  2011.    if(cnum) //draw clipped triangles
  2012.    {
  2013.    int first = 0;
  2014.  
  2015.    fan.tex = context->w3dTexBuffer[context->CurrentBinding];
  2016.    fan.st_pattern = 0;
  2017.  
  2018.      j = 0;
  2019.      do
  2020.      {
  2021.           PolyBuffer *p = &clip[j];
  2022.  
  2023.           for (i=0; i<p->numverts; i++)
  2024.           {
  2025.                 int vert = p->verts[i];
  2026.  
  2027.                 if(vert < context->VertexBufferPointer)
  2028.                 {
  2029.                    switch(visible[vert])
  2030.                    {
  2031.                         case 2:
  2032.                                 break;
  2033.                         case 1:
  2034.                                 A_ToV(context, vert);
  2035.                                 visible[vert] = 2;
  2036.                                 break;
  2037.                         default:
  2038.                                 V_ToScreen(context, vert);
  2039.                                 visible[vert] = 2;
  2040.                                 break;
  2041.                    }
  2042.                 }
  2043.           verts[i+first] = &(context->VertexBuffer[vert].v);
  2044.           }
  2045.  
  2046.           fan.vertexcount = p->numverts;
  2047.           fan.v = &verts[first];
  2048.  
  2049.           error = W3D_DrawTriFanV(context->w3dContext, &fan);
  2050.  
  2051.           first += p->numverts;
  2052.  
  2053.      j++;
  2054.      } while (j < cnum);
  2055.    }
  2056. }
  2057.  
  2058.  
  2059. void A_DrawTriangles(GLcontext context, const int first, const int count)
  2060. {
  2061.       int i,j;
  2062.     int outcode;
  2063.       static ULONG   complete;
  2064.       ULONG error;
  2065.       static W3D_Vertex **verts = NULL;
  2066.       static GLboolean visible;
  2067.       PolyBuffer clip[128]; //should be enough
  2068.       static int sign;
  2069.       int cnum, free, start;
  2070.     static int chainverts;
  2071.  
  2072.  
  2073.     if(Clip_Volume_Bypass != GL_FALSE)
  2074.     {
  2075.     //compiled arrays
  2076.  
  2077.        if(context->CullFace_State == GL_FALSE)
  2078.        {
  2079.             error = W3D_DrawArray(context->w3dContext, W3D_PRIMITIVE_TRIANGLES, first, count);
  2080.        }
  2081.        else
  2082.        {
  2083.        int start;
  2084.        float area;
  2085.        float x1,y1;
  2086.        float x2,y2;
  2087.  
  2088.        #define x(i) (context->VertexBuffer[first+i].bx)
  2089.        #define y(i) (context->VertexBuffer[first+i].by)
  2090.  
  2091.         start = 0;
  2092.         chainverts = 0;
  2093.         sign = context->CurrentCullSign;
  2094.  
  2095.         for(i=0; i<count; i+=3)
  2096.         {
  2097.            if(Clip_Volume_Bypass == GL_TRUE + 1)
  2098.            {
  2099.             if(context->VertexBuffer[first+i].outcode & context->VertexBuffer[first+i+1].outcode & context->VertexBuffer[first+i+2].outcode)
  2100.             {
  2101.                if(chainverts)
  2102.                {
  2103.                 error = W3D_DrawArray(context->w3dContext, W3D_PRIMITIVE_TRIANGLES, first + start, chainverts);
  2104.  
  2105.                 chainverts = 0;
  2106.                }
  2107.  
  2108.             continue;
  2109.             }
  2110.            }
  2111.  
  2112.             x1 = x(i+1) - x(i);
  2113.             y1 = y(i+1) - y(i);
  2114.             x2 = x(i+2) - x(i);
  2115.             y2 = y(i+2) - y(i);
  2116.  
  2117.             area = y2*x1 - x2*y1;
  2118.  
  2119.             if(sign > 0)
  2120.             area = -area;
  2121.  
  2122.             if(area < context->MinTriArea)
  2123.             {
  2124.                if(chainverts)
  2125.                {
  2126.                 error = W3D_DrawArray(context->w3dContext, W3D_PRIMITIVE_TRIANGLES, first + start, chainverts);
  2127.  
  2128.                 chainverts = 0;
  2129.                }
  2130.             }
  2131.             else
  2132.             {
  2133.                if(chainverts == 0)
  2134.                {
  2135.                 start = i;
  2136.                }
  2137.  
  2138.                chainverts += 3;
  2139.             }
  2140.         }
  2141.  
  2142.         if(chainverts) //draw remainder
  2143.         {
  2144.             error = W3D_DrawArray(context->w3dContext, W3D_PRIMITIVE_TRIANGLES, first + start, chainverts);
  2145.         }
  2146.  
  2147.        #undef x
  2148.        #undef y
  2149.        }
  2150.     return;
  2151.     }
  2152.  
  2153.     if(verts == NULL)
  2154.     {
  2155.         verts = (W3D_Vertex **)malloc(sizeof(W3D_Vertex *) * context->VertexBufferSize);
  2156.                  if (!verts) return;
  2157.     }
  2158.  
  2159.     sign = context->CurrentCullSign;
  2160.     chainverts = 0;
  2161.     cnum = 0;
  2162.     free = context->VertexBufferPointer;
  2163.     start = first;
  2164.     i = first;
  2165.  
  2166.     do
  2167.     {
  2168.        outcode = A_TransformArray(context, i, 3);
  2169.  
  2170.        if(outcode < 0)
  2171.        {
  2172.         if(chainverts)
  2173.         {
  2174.             error = W3D_DrawArray(context->w3dContext, W3D_PRIMITIVE_TRIANGLES, start, chainverts);
  2175.  
  2176.         chainverts = 0;
  2177.         }
  2178.  
  2179.        i+=3;
  2180.        }
  2181.        else
  2182.        {
  2183.         complete = (ULONG)outcode;
  2184.  
  2185.           if(complete == 0)
  2186.         {
  2187.                  A_ToScreenArray(context, i, 3);
  2188.  
  2189.            if(context->CullFace_State == GL_FALSE)
  2190.            {
  2191.             visible = GL_TRUE;
  2192.            }
  2193.            else
  2194.            {
  2195.            #define x(a) (context->VertexBuffer[a].bx)
  2196.            #define y(a) (context->VertexBuffer[a].by)
  2197.  
  2198.             float area;
  2199.             float x1,x2,y1,y2;
  2200.  
  2201.             x1 = x(i+1) - x(i);
  2202.             y1 = y(i+1) - y(i);
  2203.             x2 = x(i+2) - x(i);
  2204.             y2 = y(i+2) - y(i);
  2205.  
  2206.             area = y2*x1 - x2*y1;
  2207.  
  2208.             if(sign > 0)
  2209.             area = -area;
  2210.  
  2211.             if(area < context->MinTriArea)
  2212.                 visible = GL_FALSE;
  2213.             else
  2214.                 visible = GL_TRUE;
  2215.  
  2216.            #undef x
  2217.            #undef y
  2218.            }
  2219.  
  2220.                  if(visible)
  2221.                  {
  2222.             if(chainverts == 0)
  2223.             {
  2224.                 start = i;
  2225.                 chainverts = 3;
  2226.             }
  2227.             else
  2228.             {
  2229.                 chainverts += 3;
  2230.             }
  2231.            }
  2232.            else if (chainverts)
  2233.            {
  2234.             error = W3D_DrawArray(context->w3dContext, W3D_PRIMITIVE_TRIANGLES, start, chainverts);
  2235.  
  2236.             chainverts = 0;
  2237.            }
  2238.        i+=3;
  2239.        }
  2240.        else
  2241.        {
  2242.            if(chainverts)
  2243.            {
  2244.             error = W3D_DrawArray(context->w3dContext, W3D_PRIMITIVE_TRIANGLES, start, chainverts);
  2245.  
  2246.                 chainverts = 0;
  2247.            }
  2248.  
  2249.  
  2250.            if(context->ArrayPointer.FixpointTrans == GL_TRUE)
  2251.            {
  2252.             ConvertFixverts(context, i, 3);
  2253.            }
  2254.  
  2255.                if(context->CullFace_State == GL_FALSE || (complete & MGL_CLIP_NEGW))
  2256.                {
  2257.              visible = GL_TRUE;
  2258.                  }
  2259.                else
  2260.                {
  2261.             visible = DecideFrontface(context, &(context->VertexBuffer[i+0]), &(context->VertexBuffer[i+1]), &(context->VertexBuffer[i+2]), sign);
  2262.                }
  2263.  
  2264.                if(visible)
  2265.                {
  2266.                    Convert(context, i+0);
  2267.                    Convert(context, i+1);
  2268.                    Convert(context, i+2);
  2269.  
  2270.                    clip[cnum].numverts = 3;
  2271.                    clip[cnum].verts[0] = i+0;
  2272.                    clip[cnum].verts[1] = i+1;
  2273.                    clip[cnum].verts[2] = i+2;
  2274.  
  2275.                    AE_ClipPoly(context, &clip[cnum], free, complete);
  2276.  
  2277.                    if(clip[cnum].numverts)
  2278.                    {
  2279.              free = clip[cnum].nextfree;
  2280.              cnum++;
  2281.                    }
  2282.                }
  2283.         i+=3;
  2284.         }
  2285.        }
  2286.     } while (i < first + count);
  2287.  
  2288.  
  2289.     if(chainverts) //draw remainder of unclipped triangles
  2290.     {
  2291.         error = W3D_DrawArray(context->w3dContext, W3D_PRIMITIVE_TRIANGLES, start, chainverts);
  2292.     }
  2293.  
  2294.       if (cnum)
  2295.     {
  2296.       static W3D_TrianglesV fan;
  2297.     static PolyBuffer *p;
  2298.     static int start;
  2299.  
  2300.     fan.st_pattern = 0;
  2301.     fan.tex = context->w3dTexBuffer[context->CurrentBinding];
  2302.  
  2303.     start = 0;
  2304.     i = 0;
  2305.  
  2306.         do
  2307.         {
  2308.            p = &clip[i];
  2309.            j = 0;
  2310.  
  2311.            while (j < p->numverts)
  2312.            {
  2313.             verts[start+j] = &(context->VertexBuffer[p->verts[j]].v);
  2314.             V_ToScreen(context, p->verts[j]);
  2315.            j++;
  2316.            }
  2317.  
  2318.            fan.v = &verts[start];
  2319.            fan.vertexcount = p->numverts;
  2320.  
  2321.            start += p->numverts;
  2322.  
  2323.            error = W3D_DrawTriFanV(context->w3dContext, &fan);
  2324.  
  2325.         i++;
  2326.         } while (i < cnum);
  2327.       }
  2328. }
  2329.  
  2330. #if 0
  2331. void A_DrawTriangle(GLcontext context, const int first)
  2332. {
  2333.     int i;
  2334.     int outcode;
  2335.     ULONG complete;
  2336.       ULONG error;
  2337.       static W3D_Vertex *verts[16];
  2338.       static W3D_TrianglesV fan;
  2339.       PolyBuffer clip;
  2340.  
  2341.  
  2342.     if(Clip_Volume_Bypass != GL_FALSE)
  2343.     {
  2344.        if(context->CullFace_State == GL_FALSE)
  2345.        {
  2346.         error = W3D_DrawArray(context->w3dContext, W3D_PRIMITIVE_TRIANGLES, first, 3);
  2347.        }
  2348.        else
  2349.        {
  2350.        float area;
  2351.        float x1,y1;
  2352.        float x2,y2;
  2353.  
  2354.        #define x(i) (context->VertexBuffer[first+i].bx)
  2355.        #define y(i) (context->VertexBuffer[first+i].by)
  2356.  
  2357.             x1 = x(1) - x(0);
  2358.             y1 = y(1) - y(0);
  2359.             x2 = x(2) - x(0);
  2360.             y2 = y(2) - y(0);
  2361.  
  2362.             area = y2*x1 - x2*y1;
  2363.  
  2364.             if(context->CurrentCullSign > 0)
  2365.                 area = -area;
  2366.  
  2367.             if(area > context->MinTriArea)
  2368.             {
  2369.                 error = W3D_DrawArray(context->w3dContext, W3D_PRIMITIVE_TRIANGLES, first, 3);
  2370.             }
  2371.        #undef x
  2372.        #undef y
  2373.        }
  2374.     return;
  2375.     }
  2376.  
  2377.     outcode = A_TransformArray(context, first, 3);
  2378.  
  2379.     if(outcode < 0)
  2380.     {
  2381.         return;
  2382.     }
  2383.     else if (outcode == 0)
  2384.     {
  2385.        A_ToScreenArray(context, first, 3);
  2386.  
  2387.        if(context->CullFace_State == GL_TRUE)
  2388.        {
  2389.        float area;
  2390.        float x1,y1;
  2391.        float x2,y2;
  2392.  
  2393.        #define x(i) (context->VertexBuffer[first+i].bx)
  2394.        #define y(i) (context->VertexBuffer[first+i].by)
  2395.  
  2396.             x1 = x(1) - x(0);
  2397.             y1 = y(1) - y(0);
  2398.             x2 = x(2) - x(0);
  2399.             y2 = y(2) - y(0);
  2400.  
  2401.             area = y2*x1 - x2*y1;
  2402.  
  2403.             if(context->CurrentCullSign > 0)
  2404.                 area = -area;
  2405.  
  2406.             if(area < context->MinTriArea)
  2407.                 return;
  2408.        #undef x
  2409.        #undef y
  2410.        }
  2411.  
  2412.     error = W3D_DrawArray(context->w3dContext, W3D_PRIMITIVE_TRIANGLES, first, 3);
  2413.  
  2414.     return;
  2415.     }
  2416.  
  2417.     complete = (ULONG)outcode;
  2418.  
  2419.     if(context->CullFace_State == GL_TRUE && !(complete & MGL_CLIP_NEGW))
  2420.     {
  2421.         if(DecideFrontface(context, &(context->VertexBuffer[first]), &(context->VertexBuffer[first+1]), &(context->VertexBuffer[first+2]), context->CurrentCullSign) == GL_FALSE)
  2422.         return;
  2423.     }
  2424.  
  2425.     Convert(context, first);
  2426.     Convert(context, first+1);
  2427.     Convert(context, first+2);
  2428.  
  2429.     clip.numverts = 3;
  2430.     clip.verts[0] = first;
  2431.     clip.verts[1] = first+1;
  2432.     clip.verts[2] = first+2;
  2433.  
  2434.     AE_ClipPoly(context, &clip, context->VertexBufferPointer, complete);
  2435.  
  2436.     if(clip.numverts < 3)
  2437.         return;
  2438.  
  2439.     i = 0;
  2440.     do
  2441.     {
  2442.         verts[i] = &(context->VertexBuffer[clip.verts[i]].v);
  2443.         V_ToScreen(context, clip.verts[i]);
  2444.     i++;
  2445.     } while (i < clip.numverts);
  2446.  
  2447.     fan.st_pattern = 0;
  2448.     fan.tex = context->w3dTexBuffer[context->CurrentBinding];
  2449.     fan.v = verts;
  2450.     fan.vertexcount = clip.numverts;
  2451.  
  2452.     error = W3D_DrawTriFanV(context->w3dContext, &fan);
  2453. }
  2454. #endif
  2455.  
  2456. void A_DrawPolygon(GLcontext context, const int first, const int count)
  2457. {
  2458.     int i,j;
  2459.     int outcode;
  2460.     ULONG complete;
  2461.     ULONG error;
  2462.     GLboolean visible;    
  2463.     PolyBuffer clip;
  2464.       static W3D_Vertex **verts = NULL;
  2465.       static W3D_TrianglesV fan;
  2466.  
  2467.  
  2468.     if(Clip_Volume_Bypass != GL_FALSE)
  2469.     {
  2470.     //compiled arrays
  2471.  
  2472.        if(Clip_Volume_Bypass == GL_TRUE + 1)
  2473.        {
  2474.         ULONG and_code;
  2475.  
  2476.         and_code = 0xff;
  2477.  
  2478.         for(i=first; i<first+count; i++)
  2479.             and_code &= context->VertexBuffer[i].outcode;
  2480.  
  2481.         if(and_code)
  2482.             return;
  2483.  
  2484.        }
  2485.  
  2486.        if(context->CullFace_State == GL_TRUE)
  2487.        {
  2488.         float x0,y0;
  2489.         float x1,y1;
  2490.         float x2,y2;
  2491.         GLfloat area;
  2492.  
  2493.         #define x(a) (context->VertexBuffer[first+a].bx)
  2494.         #define y(a) (context->VertexBuffer[first+a].by)
  2495.  
  2496.         x0 = x(0);
  2497.         y0 = y(0);
  2498.         x1 = x(1) - x0;
  2499.         y1 = y(1) - y0;
  2500.         x2 = x(2) - x0;
  2501.         y2 = y(2) - y0;
  2502.  
  2503.         area = y2*x1 - x2*y1;
  2504.  
  2505.         i = 1;
  2506.  
  2507.         while (i < count-2 && fabs(area) < context->MinTriArea)
  2508.         {
  2509.            x1 = x2;
  2510.            y1 = y2;
  2511.            x2 = x(i+2) - x0;
  2512.            y2 = y(i+2) - y0;
  2513.  
  2514.            area += y2*x1 - x2*y1;
  2515.            i++;
  2516.         }        
  2517.  
  2518.         if(context->CurrentCullSign > 0)
  2519.         area = -area;
  2520.  
  2521.         if(area < context->MinTriArea)
  2522.         return;
  2523.  
  2524.         #undef x
  2525.         #undef y
  2526.        }
  2527.  
  2528.     error = W3D_DrawArray(context->w3dContext, W3D_PRIMITIVE_TRIFAN, first, count);
  2529.  
  2530.     return;
  2531.     }
  2532.  
  2533.     outcode = A_TransformArray(context, first, count);
  2534.  
  2535.     if(outcode < 0)
  2536.         return;
  2537.  
  2538.     else if(outcode == 0)
  2539.     {
  2540.        A_ToScreenArray(context, first, count);
  2541.  
  2542.        if(context->CullFace_State == GL_TRUE)
  2543.        {
  2544.         float x0,y0;
  2545.         float x1,y1;
  2546.         float x2,y2;
  2547.         GLfloat area;
  2548.  
  2549.         #define x(a) (context->VertexBuffer[first+a].bx)
  2550.         #define y(a) (context->VertexBuffer[first+a].by)
  2551.  
  2552.         x0 = x(0);
  2553.         y0 = y(0);
  2554.         x1 = x(1) - x0;
  2555.         y1 = y(1) - y0;
  2556.         x2 = x(2) - x0;
  2557.         y2 = y(2) - y0;
  2558.  
  2559.         area = y2*x1 - x2*y1;
  2560.  
  2561.         i = 1;
  2562.  
  2563.         while (i < count-2 && fabs(area) < context->MinTriArea)
  2564.         {
  2565.            x1 = x2;
  2566.            y1 = y2;
  2567.            x2 = x(i+2) - x0;
  2568.            y2 = y(i+2) - y0;
  2569.  
  2570.            area += y2*x1 - x2*y1;
  2571.            i++;
  2572.         }        
  2573.  
  2574.         if(context->CurrentCullSign > 0)
  2575.         area = -area;
  2576.  
  2577.         if(area < context->MinTriArea)
  2578.         return;
  2579.  
  2580.         #undef x
  2581.         #undef y
  2582.        }
  2583.  
  2584.     error = W3D_DrawArray(context->w3dContext, W3D_PRIMITIVE_TRIFAN, first, count);
  2585.     }
  2586.     else
  2587.     {
  2588.     complete = (ULONG)outcode;
  2589.  
  2590.         if(verts == NULL)
  2591.         {
  2592.             verts = (W3D_Vertex **)malloc(sizeof(W3D_Vertex *) * context->VertexBufferSize);
  2593.                      if (!verts) return;
  2594.         }
  2595.  
  2596.  
  2597.             if(context->ArrayPointer.FixpointTrans == GL_TRUE)
  2598.             {
  2599.            ConvertFixverts(context, first, count);
  2600.             }
  2601.  
  2602.         i = first;
  2603.         j = 0;
  2604.  
  2605.         while (i < first + count)
  2606.         {
  2607.             Convert(context, i);
  2608.             clip.verts[j++] = i;
  2609.         i++;
  2610.         }
  2611.  
  2612.         clip.numverts = count;
  2613.  
  2614.         AE_ClipPoly(context, &clip, context->VertexBufferPointer, complete);
  2615.  
  2616.         if(clip.numverts < 3)
  2617.             return;
  2618.  
  2619.         i = 0;
  2620.         do
  2621.         {
  2622.             verts[i] = &(context->VertexBuffer[clip.verts[i]].v);
  2623.  
  2624.                V_ToScreen(context, clip.verts[i]);
  2625.         i++;
  2626.         } while (i < clip.numverts);
  2627.  
  2628.  
  2629.        if(context->CullFace_State == GL_TRUE)
  2630.        {
  2631.         float x0,y0;
  2632.         float x1,y1;
  2633.         float x2,y2;
  2634.         GLfloat area;
  2635.  
  2636.         #define x(a) (context->VertexBuffer[clip.verts[a]].bx)
  2637.         #define y(a) (context->VertexBuffer[clip.verts[a]].by)
  2638.  
  2639.         x0 = x(0);
  2640.         y0 = y(0);
  2641.         x1 = x(1) - x0;
  2642.         y1 = y(1) - y0;
  2643.         x2 = x(2) - x0;
  2644.         y2 = y(2) - y0;
  2645.  
  2646.         area = y2*x1 - x2*y1;
  2647.  
  2648.         i = 1;
  2649.  
  2650.         while (i < clip.numverts-2 && fabs(area) < context->MinTriArea)
  2651.         {
  2652.            x1 = x2;
  2653.            y1 = y2;
  2654.            x2 = x(i+2) - x0;
  2655.            y2 = y(i+2) - y0;
  2656.  
  2657.            area += y2*x1 - x2*y1;
  2658.            i++;
  2659.         }        
  2660.  
  2661.         if(context->CurrentCullSign > 0)
  2662.         area = -area;
  2663.  
  2664.         if(area < context->MinTriArea)
  2665.         return;
  2666.  
  2667.         #undef x
  2668.         #undef y
  2669.        }
  2670.  
  2671.     fan.tex = context->w3dTexBuffer[context->CurrentBinding];
  2672.     fan.st_pattern = 0;
  2673.     fan.v = verts;
  2674.     fan.vertexcount = clip.numverts;
  2675.  
  2676.     error = W3D_DrawTriFanV(context->w3dContext, &fan);
  2677.     }
  2678. }
  2679.  
  2680.  
  2681. void A_DrawFlatFan(GLcontext context, const int first, const int count)
  2682. {
  2683.     int i;
  2684.     ULONG error;
  2685.      MGLVertex *v;
  2686.  
  2687.     int Vstride;
  2688.     UBYTE *Vpointer;
  2689.     int Wstride;
  2690.     UBYTE *Wpointer;
  2691.       float *W;
  2692.  
  2693.       Vstride = context->ArrayPointer.vertexstride;
  2694.       Wstride = context->ArrayPointer.texcoordstride;
  2695.  
  2696.     Wpointer = (UBYTE*)context->WBuffer + first * Wstride;
  2697.     Vpointer = context->ArrayPointer.verts + first * Vstride;
  2698.  
  2699.    v = &context->VertexBuffer[first];
  2700.  
  2701.    if(context->ArrayPointer.FixpointTrans == GL_TRUE)
  2702.    {
  2703.       int *V;
  2704.     i = count;
  2705.  
  2706.     do
  2707.     {
  2708.          V = (int*)Vpointer;
  2709.  
  2710.          v->bx = (float)V[0];
  2711.          v->by = (float)V[1];
  2712.          v->bz = (float)V[2];
  2713.  
  2714.          if(context->ClientState & GLCS_TEXTURE)
  2715.          {
  2716.         W = (float*)Wpointer;
  2717.               *W = 1.0;
  2718.          }
  2719.  
  2720.     v++; Vpointer += Vstride; Wpointer += Wstride;
  2721.       } while (--i);
  2722.    }
  2723.    else
  2724.    {
  2725.       float *V;
  2726.     i = count;
  2727.  
  2728.     do
  2729.     {
  2730.          V = (float*)Vpointer;
  2731.  
  2732.          v->bx = V[0];
  2733.          v->by = V[1];
  2734.          v->bz = V[2];
  2735.  
  2736.          if(context->ClientState & GLCS_TEXTURE)
  2737.          {
  2738.         W = (float*)Wpointer;
  2739.               *W = 1.0;
  2740.          }
  2741.  
  2742.     v++; Vpointer += Vstride; Wpointer += Wstride;
  2743.       } while (--i);
  2744.    }
  2745.  
  2746.    error = W3D_DrawArray(context->w3dContext, W3D_PRIMITIVE_TRIFAN, first, count);
  2747. }
  2748.  
  2749. //end of pipeline
  2750.  
  2751. #ifdef VA_SANITY_CHECK
  2752.  
  2753. // Swap_TextureCoordPointers added 01-06-2002
  2754. // Thanks to Olivier Fabre for making me aware of possible
  2755. // memprot problems without such a safety-check.
  2756. // It will only be needed if glTexcoordPointer,
  2757. // GL_TEXTURE_COORD_ARRAY and GL_TEXTURE_2D state are not
  2758. // in "sync".
  2759.  
  2760. void Swap_TextureCoordPointers(GLcontext context, GLboolean enable) 
  2761. {
  2762.     if(enable == GL_TRUE)
  2763.     {
  2764.         Set_W3D_TexCoordPointer(context->w3dContext, (void*)context->ArrayPointer.texcoords, context->ArrayPointer.texcoordstride, 0, sizeof(GLfloat), context->ArrayPointer.w_off, W3D_TEXCOORD_NORMALIZED);
  2765.     }
  2766.     else
  2767.     {
  2768.     // guaranteed valid spot as long as vertexbuffer
  2769.     // is big enough
  2770.  
  2771.         Set_W3D_TexCoordPointer(context->w3dContext, (void*)&context->VertexBuffer[0].v.u, sizeof(MGLVertex), 0, 4, -4, W3D_TEXCOORD_NORMALIZED);
  2772.     }
  2773. }
  2774.  
  2775. #else
  2776.  
  2777.     #define Swap_TextureCoordPointers(c,e) {}
  2778.  
  2779. #endif
  2780.  
  2781. void GLEnableClientState(GLcontext context, GLenum state)
  2782. {
  2783.         switch (state)
  2784.         {
  2785.                 case GL_TEXTURE_COORD_ARRAY:
  2786.             context->ClientState |= GLCS_TEXTURE;
  2787.             Swap_TextureCoordPointers(context, GL_TRUE); 
  2788.             break;
  2789.  
  2790.                 case GL_COLOR_ARRAY:
  2791.                       context->ClientState |= GLCS_COLOR;
  2792.                       break;
  2793.  
  2794.                 case GL_VERTEX_ARRAY:
  2795.                       context->ClientState |= GLCS_VERTEX;
  2796.                       break;
  2797.  
  2798.                 default:
  2799.                         GLFlagError(context, 1, GL_INVALID_ENUM);
  2800.                 break;
  2801.         }
  2802. }
  2803.  
  2804.  
  2805. void GLDisableClientState(GLcontext context, GLenum state)
  2806. {
  2807.         switch (state)
  2808.         {
  2809.                 case GL_TEXTURE_COORD_ARRAY:
  2810.                         context->ClientState &= ~GLCS_TEXTURE;
  2811.               Swap_TextureCoordPointers(context, GL_FALSE); 
  2812.                         break;
  2813.  
  2814.                 case GL_COLOR_ARRAY:
  2815.                         context->ClientState &= ~GLCS_COLOR;
  2816.                         break;
  2817.  
  2818.                 case GL_VERTEX_ARRAY:
  2819.                         context->ClientState &= ~GLCS_VERTEX;
  2820.                         break;
  2821.  
  2822.                 default:
  2823.                         GLFlagError(context, 1, GL_INVALID_ENUM);
  2824.                         break;
  2825.         }
  2826.  
  2827. }
  2828.  
  2829. #if 0 //NYI
  2830.  
  2831. void GLInterleavedArrays(GLcontext context, GLenum format, GLsizei stride, const GLvoid *pointer)
  2832. {
  2833.  
  2834.    #define PTR context->ArrayPointer
  2835.  
  2836.    PTR.colorpointer = NULL;
  2837.    PTR.texcoordpointer = NULL;
  2838.  
  2839.    switch((int)format)
  2840.    {
  2841.     case GL_V2F:
  2842.         context->ClientState = GLCS_VERTEX;
  2843.         PTR.verts = (UBYTE *)pointer;
  2844.         if(stride == 0)
  2845.             PTR.vertexstride = 2*sizeof(GLfloat);
  2846.         else
  2847.             PTR.vertexstride = stride;
  2848.     break;
  2849.     case GL_V3F:
  2850.         context->ClientState = GLCS_VERTEX;
  2851.         PTR.verts = (UBYTE *)pointer;
  2852.         if(stride == 0)
  2853.             PTR.vertexstride = 3*sizeof(GLfloat);
  2854.         else
  2855.             PTR.vertexstride = stride;
  2856.     break;
  2857.     case GL_C4UB_V2F:
  2858.         context->ClientState = GLCS_VERTEX|GLCS_COLOR;
  2859.         PTR.colors = (UBYTE *)pointer;
  2860.         PTR.verts = ((UBYTE *)pointer + 4);
  2861.         PTR.colormode = W3D_COLOR_UBYTE | W3D_CMODE_RGBA;
  2862.         if(stride == 0)
  2863.         {
  2864.             PTR.vertexstride = PTR.colorstride = 2*sizeof(GLfloat) + 4*sizeof(GLubyte);
  2865.         }
  2866.         else
  2867.         {
  2868.             PTR.vertexstride = PTR.colorstride = stride;
  2869.         }
  2870.     break;
  2871.     case GL_C4UB_V3F:
  2872.         context->ClientState = GLCS_VERTEX|GLCS_COLOR;
  2873.         PTR.colors = (UBYTE *)pointer;
  2874.         PTR.verts = ((UBYTE *)pointer + 4);
  2875.         PTR.colormode = W3D_COLOR_UBYTE | W3D_CMODE_RGBA;
  2876.         if(stride == 0)
  2877.         {
  2878.             PTR.vertexstride = PTR.colorstride = 3*sizeof(GLfloat) + 4*sizeof(GLubyte);
  2879.         }
  2880.         else
  2881.         {
  2882.             PTR.vertexstride = PTR.colorstride = stride;
  2883.         }
  2884.     break;
  2885.     case GL_C3F_V3F:
  2886.         context->ClientState = GLCS_VERTEX|GLCS_COLOR;
  2887.         PTR.colors = (UBYTE *)pointer;
  2888.         PTR.verts = ((UBYTE *)pointer + 12);
  2889.         PTR.colormode = W3D_COLOR_FLOAT | W3D_CMODE_RGB;
  2890.  
  2891.         if(stride == 0)
  2892.         {
  2893.             PTR.vertexstride = PTR.colorstride = 6*sizeof(GLfloat);
  2894.         }
  2895.         else
  2896.         {
  2897.             PTR.vertexstride = PTR.colorstride = stride;
  2898.         }
  2899.     break;
  2900.     case GL_T2F_V3F:
  2901.         context->ClientState = GLCS_VERTEX|GLCS_TEXTURE;
  2902.         PTR.texcoords = (UBYTE *)pointer;
  2903.         PTR.verts = ((UBYTE *)pointer + 8);
  2904.         if(stride == 0)
  2905.         {
  2906.             PTR.vertexstride = PTR.texcoordstride = 5*sizeof(GLfloat);
  2907.         }
  2908.         else
  2909.         {
  2910.             PTR.vertexstride = PTR.texcoordstride = stride;
  2911.         }
  2912.     break;
  2913.     case GL_T2F_C4UB_V3F:
  2914.         context->ClientState = GLCS_VERTEX|GLCS_TEXTURE|GLCS_COLOR;
  2915.         PTR.texcoords = (UBYTE *)pointer;
  2916.         PTR.colors = ((UBYTE *)pointer + 8);
  2917.         PTR.verts = ((UBYTE *)pointer + 12);
  2918.         PTR.colormode = W3D_COLOR_UBYTE | W3D_CMODE_RGBA;
  2919.         if(stride == 0)
  2920.         {
  2921.             PTR.vertexstride = PTR.colorstride = PTR.texcoordstride = 5*sizeof(GLfloat) + 4*sizeof(GLubyte);
  2922.         }
  2923.         else
  2924.         {
  2925.             PTR.vertexstride = PTR.colorstride = PTR.texcoordstride = stride;
  2926.         }
  2927.     break;
  2928.     case GL_T2F_C3F_V3F:
  2929.         context->ClientState = GLCS_VERTEX|GLCS_TEXTURE|GLCS_COLOR;
  2930.         PTR.texcoords = (UBYTE *)pointer;
  2931.         PTR.colors = ((UBYTE *)pointer + 8);
  2932.         PTR.verts = ((UBYTE *)pointer + 20);
  2933.         PTR.colormode = W3D_COLOR_FLOAT | W3D_CMODE_RGB;
  2934.         if(stride == 0)
  2935.         {
  2936.             PTR.vertexstride = PTR.colorstride = PTR.texcoordstride = 8*sizeof(GLfloat);
  2937.         }
  2938.         else
  2939.         {
  2940.             PTR.vertexstride = PTR.colorstride = PTR.texcoordstride = stride;
  2941.         }
  2942.     break;
  2943.    }
  2944.  
  2945.    #undef PTR
  2946.  
  2947. }
  2948.  
  2949. #endif
  2950.  
  2951.  
  2952. static GLboolean cur_pipeline_state = GL_TRUE;
  2953.  
  2954. void GLTexCoordPointer(GLcontext context, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
  2955. {
  2956.    int w3dStride;
  2957.    int w_off;
  2958.    BYTE *base, *target;
  2959.  
  2960. //check pipeline state to make sure that w_off was calculated:
  2961.  
  2962.     if((context->VertexArrayPipeline == cur_pipeline_state) && (context->ArrayPointer.texcoords == (UBYTE*)pointer))
  2963.         return;
  2964.  
  2965.  
  2966. #ifdef VA_SANITY_CHECK
  2967.  
  2968.     if(!pointer) //thanks to OF for making me aware..
  2969.     {
  2970.     context->ArrayPointer.texcoords = (UBYTE*)&context->VertexBuffer[0].v.u;
  2971.     context->ArrayPointer.texcoordstride = sizeof(MGLVertex);
  2972.     context->ArrayPointer.w_off = -4;
  2973.     
  2974.       Set_W3D_TexCoordPointer(context->w3dContext, (void*)&context->VertexBuffer[0].v.u, sizeof(MGLVertex), 0, sizeof(GLfloat), -4, W3D_TEXCOORD_NORMALIZED);
  2975.  
  2976.     return;
  2977.     }
  2978.  
  2979. #endif
  2980.  
  2981.     if (stride == 0)    w3dStride = size*sizeof(GLfloat);
  2982.     else        w3dStride = stride;
  2983.  
  2984.     if (type != GL_FLOAT)   GLFlagError(context, 1, GL_INVALID_ENUM);
  2985.  
  2986.     context->ArrayPointer.texcoords = (UBYTE*)pointer;
  2987.     context->ArrayPointer.texcoordstride = w3dStride;
  2988.  
  2989.     cur_pipeline_state = context->VertexArrayPipeline;
  2990.  
  2991.     if(context->VertexArrayPipeline == GL_FALSE)
  2992.     {
  2993.         if (size != 4)          GLFlagError(context, 1, GL_INVALID_VALUE);
  2994.  
  2995.     Set_W3D_TexCoordPointer(context->w3dContext, (void*)context->ArrayPointer.texcoords, 4*sizeof(GLfloat), 0, sizeof(GLfloat), 3*sizeof(GLfloat), W3D_TEXCOORD_NORMALIZED);
  2996.     }
  2997.     else
  2998.     {
  2999.       //find w_array-offset relative to current pointer:
  3000.  
  3001.     target = (BYTE*)&context->WBuffer[0];
  3002.     base   = (BYTE*)pointer;
  3003.  
  3004.     if(target < base)
  3005.     {
  3006.         w_off = (base - target);
  3007.         w_off = -w_off;    
  3008.     }
  3009.     else
  3010.     {
  3011.         w_off = (target - base);
  3012.     }
  3013.  
  3014.     context->ArrayPointer.w_off = w_off;
  3015.  
  3016.       Set_W3D_TexCoordPointer(context->w3dContext, (void*)context->ArrayPointer.texcoords, w3dStride, 0, sizeof(GLfloat), w_off, W3D_TEXCOORD_NORMALIZED);
  3017.    }
  3018. }
  3019.  
  3020.  
  3021. void GLColorPointer(GLcontext context, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
  3022. {
  3023.     int w3dStride;
  3024.     ULONG w3dType, w3dFormat;
  3025.  
  3026.     if(context->ArrayPointer.colors == (UBYTE*)pointer)
  3027.         return;
  3028.  
  3029. #ifdef VA_SANITY_CHECK
  3030.  
  3031.     if(!pointer) //thanks to OF for making me aware..
  3032.     {
  3033.     context->ArrayPointer.colors = (UBYTE*)&context->VertexBuffer[0].color[0];
  3034.       context->ArrayPointer.colorstride = sizeof(MGLVertex);
  3035.     context->ArrayPointer.colormode = W3D_COLOR_UBYTE | W3D_CMODE_RGBA;
  3036.       Convert = (Convfn)Convert_UB_RGBA;
  3037.  
  3038.       Set_W3D_ColorPointer(context->w3dContext, (void *)&context->VertexBuffer[0].color[0], sizeof(MGLVertex),
  3039.             W3D_COLOR_UBYTE, W3D_CMODE_RGBA, 0);
  3040.  
  3041.     return;
  3042.     }
  3043.  
  3044. #endif
  3045.  
  3046.     if (type != GL_UNSIGNED_BYTE && type != GL_FLOAT && type != MGL_UBYTE_BGRA && type != MGL_UBYTE_ARGB)
  3047.         GLFlagError(context, 1, GL_INVALID_ENUM);
  3048.  
  3049.     if (stride == 0)
  3050.         w3dStride = size * (type == GL_FLOAT ? sizeof(GLfloat) : sizeof(GLubyte));
  3051.     else
  3052.         w3dStride = stride;
  3053.  
  3054.     context->ArrayPointer.colors = (UBYTE*)pointer;
  3055.     context->ArrayPointer.colorstride = w3dStride;
  3056.  
  3057.  
  3058.     if(type == GL_FLOAT)
  3059.     w3dType = W3D_COLOR_FLOAT;
  3060.     else
  3061.     w3dType = W3D_COLOR_UBYTE;
  3062.  
  3063.  
  3064.     if (type != MGL_UBYTE_ARGB)
  3065.     {
  3066.       if(type == GL_FLOAT)
  3067.       {
  3068.         if(size == 3)
  3069.         {
  3070.            w3dFormat = W3D_CMODE_RGB;
  3071.              Convert   = (Convfn)Convert_F_RGB;
  3072.         }
  3073.         else
  3074.         {
  3075.            w3dFormat = W3D_CMODE_RGBA;
  3076.              Convert   = (Convfn)Convert_F_RGBA;
  3077.         }
  3078.       }
  3079.       else if (type == MGL_UBYTE_BGRA)
  3080.       {
  3081.         if(size == 3)
  3082.         {
  3083.            w3dFormat = W3D_CMODE_BGR;
  3084.            Convert   = (Convfn)Convert_UB_BGR;
  3085.         }
  3086.         else
  3087.         {
  3088.            w3dFormat = W3D_CMODE_BGRA;
  3089.            Convert   = (Convfn)Convert_UB_BGRA;
  3090.         }
  3091.       }
  3092.       else // GL_UNSIGNED_BYTE
  3093.       {
  3094.         if(size == 3)
  3095.         {
  3096.            w3dFormat = W3D_CMODE_RGB;
  3097.              Convert   = (Convfn)Convert_UB_RGB;
  3098.         }
  3099.         else
  3100.         {
  3101.            w3dFormat = W3D_CMODE_RGBA;
  3102.              Convert   = (Convfn)Convert_UB_RGBA;
  3103.         }
  3104.       }
  3105.     }
  3106.     else
  3107.     {
  3108.         w3dFormat = W3D_CMODE_ARGB;
  3109.         Convert   = (Convfn)Convert_UB_ARGB;
  3110.     }
  3111.  
  3112.     context->ArrayPointer.colormode = w3dType | w3dFormat;
  3113.  
  3114.     Set_W3D_ColorPointer(context->w3dContext, (void *)context->ArrayPointer.colors, w3dStride, w3dType, w3dFormat, 0);
  3115. }
  3116.  
  3117.  
  3118. void GLVertexPointer(GLcontext context, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
  3119. {
  3120.     int w3dStride;
  3121.  
  3122.     if (size < 3 || type != GL_FLOAT || type != GL_INT)
  3123.     GLFlagError(context, 1, GL_INVALID_VALUE);
  3124.  
  3125.     if(context->ArrayPointer.verts == (UBYTE*)pointer)
  3126.         return;
  3127.  
  3128. #ifdef VA_SANITY_CHECK
  3129.  
  3130.     if(!pointer) //thanks to OF for making me aware..
  3131.     {
  3132.     context->ArrayPointer.verts = (UBYTE*)&context->VertexBuffer[0].bx;
  3133.     context->ArrayPointer.vertexstride = sizeof(MGLVertex);
  3134.  
  3135.  
  3136.     if (Reset_W3D_VertexPointer == GL_TRUE)
  3137.     {
  3138.         Set_W3D_VertexPointer(context->w3dContext, (void *) &(context->VertexBuffer->bx), sizeof(MGLVertex), W3D_VERTEX_F_F_F, 0);
  3139.     Reset_W3D_VertexPointer = GL_FALSE;
  3140.     }
  3141.  
  3142.     return;
  3143.     }
  3144.  
  3145. #endif
  3146.  
  3147.     if(type == GL_INT)
  3148.     {
  3149.     context->ArrayPointer.FixpointTrans = GL_TRUE;
  3150.       if (stride == 0) w3dStride = size * sizeof(GLint);
  3151.     else w3dStride = stride;
  3152.     }
  3153.     else
  3154.     {
  3155.     context->ArrayPointer.FixpointTrans = GL_FALSE;
  3156.       if (stride == 0) w3dStride = size * sizeof(GLfloat);
  3157.     else w3dStride = stride;
  3158.     }
  3159.  
  3160.     context->ArrayPointer.verts = (UBYTE*)pointer;
  3161.     context->ArrayPointer.vertexstride = w3dStride;
  3162.  
  3163.  
  3164.     if(context->VertexArrayPipeline == GL_FALSE)
  3165.     {
  3166.     if(type == GL_INT)
  3167.       GLFlagError(context, 1, GL_INVALID_VALUE);
  3168.  
  3169.     Reset_W3D_VertexPointer = GL_TRUE; //not default
  3170.  
  3171.     Set_W3D_VertexPointer(context->w3dContext, (void *)pointer, w3dStride, W3D_VERTEX_F_F_F, 0);
  3172.     }
  3173.     else if (Reset_W3D_VertexPointer == GL_TRUE)
  3174.     {
  3175.     Set_W3D_VertexPointer(context->w3dContext, (void *) &(context->VertexBuffer->bx), sizeof(MGLVertex), W3D_VERTEX_F_F_F, 0);
  3176.  
  3177.     Reset_W3D_VertexPointer = GL_FALSE;
  3178.     }
  3179. }
  3180.  
  3181.  
  3182. static INLINE void PreDraw(GLcontext context)
  3183. {
  3184.    if (context->FogDirty && context->Fog_State)
  3185.    {
  3186.         fog_Set(context);
  3187.         context->FogDirty = GL_FALSE;
  3188.    }
  3189.  
  3190.    if (context->ShadeModel == GL_FLAT && context->UpdateCurrentColor == GL_TRUE)
  3191.    {
  3192.     context->UpdateCurrentColor = GL_FALSE;
  3193.     W3D_SetCurrentColor(context->w3dContext, &context->CurrentColor);
  3194.    }
  3195.  
  3196. #ifdef AUTOMATIC_LOCKING_ENABLE
  3197.  
  3198.    if (context->LockMode == MGL_LOCK_MANUAL)
  3199.         return;
  3200.  
  3201.    else if (context->LockMode == MGL_LOCK_AUTOMATIC) // Automatic: Lock per primitive
  3202.    {
  3203.         if (W3D_SUCCESS == W3D_LockHardware(context->w3dContext))
  3204.         {
  3205.                 context->w3dLocked = GL_TRUE;
  3206.         }
  3207.         else
  3208.         {
  3209.                 printf("Error during LockHardware\n");
  3210.         }
  3211.    }
  3212.    else // Smart: Lock timer based
  3213.    {
  3214.         if (context->w3dLocked == GL_FALSE)
  3215.         {
  3216.             if (W3D_SUCCESS != W3D_LockHardware(context->w3dContext))
  3217.             {
  3218.                 return; // give up
  3219.             }
  3220.             context->w3dLocked = GL_TRUE;
  3221.             TMA_Start(&(context->LockTime));
  3222.         }
  3223.    }
  3224. #endif
  3225.  
  3226. }
  3227.  
  3228.  
  3229. static INLINE void PostDraw(GLcontext context)
  3230. {
  3231.     context->VertexBufferPointer = 0;
  3232.  
  3233. #ifdef AUTOMATIC_LOCKING_ENABLE
  3234.  
  3235.     if (context->LockMode == MGL_LOCK_SMART && TMA_Check(&(context->LockTime)) == GL_TRUE)
  3236.     {
  3237.         // Time to unlock
  3238.         W3D_UnLockHardware(context->w3dContext);
  3239.         context->w3dLocked = GL_FALSE;
  3240.     }
  3241.     else if (context->LockMode == MGL_LOCK_AUTOMATIC)
  3242.     {
  3243.                 W3D_UnLockHardware(context->w3dContext);
  3244.                 context->w3dLocked = GL_FALSE;
  3245.     }
  3246.  
  3247. #endif
  3248. }
  3249.  
  3250.  
  3251. void GLDrawArrays(GLcontext context, GLenum mode, const GLint first, const GLsizei count)
  3252. {
  3253.    ULONG error, prim;
  3254.    int k;
  3255.  
  3256. #ifdef VA_SANITY_CHECK
  3257.    GLboolean ShadeModel_bypass;
  3258.    GLboolean TexCoord_bypass;
  3259. #endif
  3260.  
  3261.    //11-04-02 - check for compiled arrays
  3262.    //sorry - no time to write proper handling for this.
  3263.    //Anyways, glDrawArrays is rarely used within a lock.
  3264.  
  3265.    if(context->ArrayPointer.transformed == GL_TRUE && Clip_Volume_Bypass == GL_FALSE)
  3266.    {
  3267.     GLDrawElements(context, mode, count, GL_UNSIGNED_SHORT, (void*)&(e_wrap[first]));
  3268.     return;
  3269.    }
  3270.  
  3271.  
  3272. #ifdef VA_SANITY_CHECK
  3273.  
  3274.    ShadeModel_bypass = GL_FALSE;
  3275.  
  3276.    //Thanks to OF for making me aware of this unlikely case
  3277.  
  3278.    if(!(context->ClientState & GLCS_COLOR) && context->ShadeModel == GL_SMOOTH)
  3279.    {
  3280.     W3D_SetState(context->w3dContext, W3D_GOURAUD, W3D_DISABLE);
  3281.     context->ShadeModel = GL_FLAT;
  3282.        ShadeModel_bypass = GL_TRUE;
  3283.    }
  3284.  
  3285. #endif
  3286.  
  3287.    PreDraw(context);
  3288.  
  3289. #ifdef VA_SANITY_CHECK
  3290.  
  3291.    TexCoord_bypass = GL_FALSE;
  3292.  
  3293.    if(context->Texture2D_State[0] == GL_FALSE || !(context->ClientState & GLCS_TEXTURE))
  3294.    {
  3295.       Set_W3D_Texture(context->w3dContext, 0, NULL);
  3296.  
  3297.     if(context->ClientState & GLCS_TEXTURE)
  3298.     {
  3299.        context->ClientState &= ~GLCS_TEXTURE;
  3300.        TexCoord_bypass = GL_TRUE;
  3301.     }
  3302.    }
  3303.  
  3304. #else
  3305.  
  3306.    if(context->Texture2D_State[0] == GL_FALSE)
  3307.    {
  3308.       Set_W3D_Texture(context->w3dContext, 0, NULL);
  3309.    }
  3310.  
  3311. #endif
  3312.  
  3313.    else
  3314.    {
  3315.         Set_W3D_Texture(context->w3dContext, 0, context->w3dTexBuffer[context->CurrentBinding]);
  3316.    }
  3317.  
  3318.    if(context->VertexArrayPipeline == GL_FALSE)
  3319.    {
  3320.     switch(mode)
  3321.     {
  3322.         case GL_POINTS:
  3323.         prim = W3D_PRIMITIVE_POINTS;
  3324.         break;
  3325.         case GL_LINE_STRIP:
  3326.         prim = W3D_PRIMITIVE_LINESTRIP;
  3327.         break;
  3328.         case GL_LINE_LOOP:
  3329.         prim = W3D_PRIMITIVE_LINELOOP;
  3330.         break;
  3331.         case GL_LINES:
  3332.         prim = W3D_PRIMITIVE_LINES;
  3333.         break;
  3334.         case GL_TRIANGLE_STRIP:
  3335.         prim = W3D_PRIMITIVE_TRISTRIP;
  3336.         break;
  3337.         case MGL_FLATFAN:
  3338.       case GL_POLYGON:
  3339.         case GL_TRIANGLE_FAN:
  3340.          prim = W3D_PRIMITIVE_TRIFAN;
  3341.         break;
  3342.         case GL_TRIANGLES:
  3343.         prim = W3D_PRIMITIVE_TRIANGLES;
  3344.         break;
  3345.         default:
  3346.             GLFlagError(context, 1, GL_INVALID_ENUM);
  3347.     }
  3348.  
  3349.     error = W3D_DrawArray(context->w3dContext, prim, first, count);
  3350.  
  3351.    }
  3352.    else
  3353.    {
  3354.     if(context->ArrayPointer.transformed == GL_TRUE)
  3355.     {
  3356.         context->VertexBufferPointer = context->ArrayPointer.lockfirst + context->ArrayPointer.locksize;
  3357.     }
  3358.     else
  3359.     {
  3360.         context->VertexBufferPointer = first + count;
  3361.     }
  3362. #if 0
  3363.     if((count == 3) && (mode != MGL_FLATFAN))
  3364.     {
  3365.         A_DrawTriangle(context, first);
  3366.     }
  3367.     else
  3368. #endif
  3369.     switch(mode)
  3370.     {
  3371.           case GL_TRIANGLE_STRIP:
  3372.           A_DrawTriStrip(context, first, count);
  3373.         break;
  3374.  
  3375.             case GL_TRIANGLE_FAN:
  3376.           A_DrawTriFan(context, first, count);
  3377.         break;
  3378.  
  3379.             case GL_TRIANGLES:
  3380.           A_DrawTriangles(context, first, count);
  3381.         break;
  3382.  
  3383.             case GL_POLYGON:
  3384.           A_DrawPolygon(context, first, count);
  3385.         break;
  3386.  
  3387.         case MGL_FLATFAN:
  3388.         A_DrawFlatFan(context, first, count);
  3389.            break;
  3390.  
  3391.             default:
  3392.            GLFlagError(context, 1, GL_INVALID_ENUM);
  3393.     }
  3394.    }
  3395.  
  3396.    PostDraw(context);
  3397.  
  3398. #ifdef VA_SANITY_CHECK
  3399.  
  3400.    if(ShadeModel_bypass == GL_TRUE)
  3401.    {
  3402.     W3D_SetState(context->w3dContext, W3D_GOURAUD, W3D_ENABLE);
  3403.     context->ShadeModel = GL_SMOOTH;
  3404.    }
  3405.  
  3406.    if(TexCoord_bypass == GL_TRUE)
  3407.    {
  3408.     context->ClientState |= GLCS_TEXTURE;
  3409.    }
  3410.  
  3411. #endif
  3412.  
  3413. }
  3414.  
  3415. #ifdef __VBCC__
  3416. #undef V_ToScreen
  3417. #undef A_ToV
  3418. #endif
  3419.